Тип условного параметра в TypeScript - PullRequest
1 голос
/ 09 июля 2020

У меня здесь есть эта функция, где тип первого аргумента зависит от того, является ли второй аргумент истинным или ложным.

Итак, если userExists истинно, данные должны быть строкой, иначе - числом. Но я продолжаю видеть ошибки.

Может ли кто-нибудь помочь, где я ошибаюсь?

type DataType<T> = T extends boolean ? string : number

const makeUsername = async <T extends boolean>({
  data,
  userExists,
}: {
  data: DataType<T>,
  userExists: T
}) => {

  if (userExists) {
    // data type should be string
  } else {
    // data type should be number
  }
}

1 Ответ

2 голосов
/ 09 июля 2020

Похоже, вы пытаетесь построить что-то вроде:

type StringOrNumber<T extends boolean> = T extends true ? string : number

Но это не будет использоваться при анализе потока. Таким образом, в блоке if вы не получите ввод правильного типа.

function makeUsername<T extends boolean>({ data, userExists }: { data: StringOrNumber<T>; userExists: T }): any {
  if (userExists) {
    // But data here is still StringOrNumber<T>. You have to cast it manually.
    const dataStr = data as string;
  } else {
    const dataNum = data as number;
  }
}

// While on call side it works well
makeUsername({data: '12', userExists: true}) // ok
makeUsername({data: 12, userExists: true}) // error

Но, вероятно, здесь больше подходят перегрузки функций:

function makeUsername({ data, userExists }: { data: string; userExists: true }): any;
function makeUsername({ data, userExists }: { data: number; userExists: false }): any;
function makeUsername({ data, userExists }: { data: string | number; userExists: boolean }): any {     
  if (userExists) {
    // Here you have to cast types anyway...
    const dataStr = data as string;
  } else {
    const dataNum = data as number;
  }
}

// But on call side, this will also works as expected.
makeUsername({ data: 'kyo', userExists: true }) // ok
makeUsername({ data: 'kyo', userExists: false }); // error
...