Home > other >  Copy property from other type
Copy property from other type

Time:11-25

I have a type Command

export type Command<
  Type extends string = string,
> = {
  type: Type
}

I'm creating a type Handler like this:

export type Handler<T extends Command> = {
  type: Pick<T, 'type'>
}

The goal is to make sure that the type of the returned Handler here is the same as for the command:

export type MyCommand = Command<'MyCommand'>

const MyHandler = (): Handler<MyCommand> => {
  return {
    type: 'MyCommand'
  }
}

But I'm getting this error:

Type 'string' is not assignable to type 'Pick<MyCommand, "type">'.(2322)

I've created TS playground here.

CodePudding user response:

Pick<T, K> creates an object type that contains the properties specified in K. So Pick<MyCommand, 'type'> is actually { type: 'MyCommand' }

If you just want the type of a property in another type use an index accessed type T[K]

export type Command<
  Type extends string = string,
> = {
  type: Type
}

export type Handler<T extends Command> = {
  type: T['type']
}

export type MyCommand = Command<'MyCommand'>

const MyHandler = (): Handler<MyCommand> => {
  return {
    type: 'MyCommand'
  }
}

Playground Link

CodePudding user response:

You can infer Type generic type from Command inside Handler like this:

export type Handler<T> = T extends Command<infer Type> 
  ? {type: Type} 
  : never;

Following description is how I understand inference in this case.

Here we have ternary type where we check that T in fact extends Command. If it doesn't extends Command, we return never, as it should never happen. But if it does, we infer (get type) value of Command generic and put it into some kind of type variable Type. Then we return {type: Type} as a value of our Handler.

  • Related