Typescript: получить литеральное значение из универсального типа - PullRequest
0 голосов
/ 10 октября 2019

Можно ли получить литеральное значение из типа? Например:

const createRecord = <T>(type: T, data: number) => ({ type, data })
const r = createRecord<'TYPE_1'>('TYPE_1', 101)

// The type of `r` is { type: "TYPE_1"; data: number; }

Но я хотел бы опустить первый параметр и просто написать:

const createRecord = <T>(data: number) => ({ type: typeof T, data })
const r = createRecord<'TYPE_1'>(101)

Конечно, предыдущий пример не работает, потому что typeof T является типом, не значение.

Ответы [ 2 ]

1 голос
/ 10 октября 2019

Ваша функция createRecord возвращает объект, а объект является значением, поэтому свойство type также должно иметь значение, а не только тип. Вместо этого вы можете позволить TypeScript выводить тип для T из заданного вами значения. TypeScript выводит литеральный тип только в том случае, если вы ограничили универсальный тип string (или number и т. Д.).

. Вы можете создать такую ​​функцию:

const createRecord2 = <T extends string>(type: T, data: number) => ({ type, data })

, а затемвы делаете

const r2 = createRecord2('TYPE_1', 101)

r2.type // type is inferred as 'TYPE_1'

Обратите внимание, что я не указываю тип для T при вызове, он выводится из заданного аргумента.

Смотрите здесь разницу: детская площадка

0 голосов
/ 10 октября 2019

Как сказал Даниэль в предыдущем сообщении, мы можем вывести универсальные типы из параметров. Проблема в том, что функция может содержать несколько универсальных типов, и TypeScript не позволяет опускать некоторые из них (однако вы можете опустить все). Итак, вот обходной путь к проблеме:

const createRecord = <S, T extends string>(type: T, data: S) => ({ type, data })
const r = createRecord('TYPE_1', 101)
// type of `r` is const r: { type: "TYPE_1"; data: number; }

Обратите внимание, что универсальные типы T и S выводятся из параметров type и data. Однако вы не можете сделать это:

const createRecord = <S, T extends string>(type: T, data: S) => ({ type, data })
const r = createRecord<number>('TYPE_1', 101)
// Expected 2 type arguments, but got 1.

Также обратите внимание, что T должен расширять строку для получения строкового литерала (в противном случае тип будет просто string).

...