0

In the follow example

type Message = string

type CommandWithArgsProps<Args> = {
  args: true
  argsRequired: boolean
  resolveFromArgs(args: string[], message: Message): Promise<Args>
}

export type Command<Args extends unknown = never> = {
  name?: string
  description: string
  execute(message: Message, args: Args): Promise<unknown>
} & (Args extends never ? Record<string, never> : CommandWithArgsProps<Args>)

I would like

const x: Command = {
  description: "",
  async execute() {
    return ""
  },
}

To be valid, however this errors with Type '{}' is not assignable to type 'never'. When I add the generic parameter I would like to extend the Command type with the CommandWithArgsProps type

  • See [this other Q&A](https://stackoverflow.com/q/65492464/12299000) for an explanation of why `extends never` doesn't do what you want. – kaya3 Jan 03 '21 at 14:06

1 Answers1

0

If you want to make optional Args generic, you should use void instead of never - <Args = void>.

Type: Record<string, never> simply means empty object. BEcause it is impossible to create object with key string and value never. I think it is worth using here just {} instead of Record<string, never>.

And the last one, if you want check if generic was provided :Args extends never ? Record<string, never> , please use Args extends void ....

Complete code:

type Message = string

type CommandWithArgsProps<Args> = {
  args: true
  argsRequired: boolean
  resolveFromArgs(args: string[], message: Message): Promise<Args>
}

export type Command<Args = void> = {
  name?: string
  description: string
  execute(message: Message, args: Args): Promise<unknown>
} & (Args extends void ? {} : CommandWithArgsProps<Args>)


const x: Command<{ arg: number }> = {
  description: "",
  async execute() {
    return ""
  },
  args: true,
  argsRequired: true,
  resolveFromArgs(args: string[], message: Message) {
    return Promise.resolve({ arg: 42 })
  }
}

const y: Command = {
  description: "",
  async execute() {
    return ""
  },
}