#typescript #generics #typescript-generics #conditional-types
Вопрос:
У меня есть тип, содержащий некоторые условные обозначения (обратите внимание, что это не мой фактический код, а урезанная версия, которая пытается выделить проблему с наименьшим количеством кода).
type A<T> = {
prop: T;
value:
T extends string ? { a: T, b: T } :
T extends number ? { y: T, z: T } :
never
}
Создание экземпляров переменных с этим типом работает нормально. Например.
// works
const a_string: A<string> = {
prop: '',
value: { a: '', b: ''}
}
// works
const a_number: A<number> = {
prop: 0,
value: { y: 1, z: 1}
}
// errors (as expected)
const a_mistake: A<number> = {
prop: 0,
value: { a: '', b: '' } <-- Should be { y:number, z: number }
}
Моя проблема заключается в том, что я пытаюсь создать эту функцию:
function myFunc<T extends string>(prop: T): A<T> {
return {
prop,
value: { a: prop, b: prop }
}
}
Я не могу понять, почему это не работает. Машинописный текст жалуется, что то, что я возвращаю, не может быть присвоено:
Type '{ a: T; b: T; }' is not assignable to type 'T extends string ? { a: T; b: T; } : T extends number ? { y: T; z: T; } : never'.ts(2322)
union.ts(33, 3): The expected type comes from property 'value' which is declared here on type 'A<T>'
Хоть убей, я не могу понять, почему?
Комментарии:
1. Поскольку ваша
T
расширенная строка, почему бы вам просто не использоватьA<string>
ее в качестве возвращаемого типа? РассматривайтеA<T>
как тип, который не был оценен, это просто условный тип. И тип состояния сам по себе не может быть присвоенvalue
2. Пример не охватывает все фактические случаи, которые охватывает мой код. У меня есть сложные объекты, которые передаются (не только примитивы , такие как
string
и т.number
Д.). Жесткое кодирование возвращенногоA
значенияA<Object>
означает, что я теряю информацию о типе. например, еслиT
были{ some: 'complex', type: 2 }
3. Я думаю, что стоит создать словарь для всех ваших случаев вместо условного ввода
4. Можете ли вы объяснить подробнее?
5. Как я понял
myFUnc
, содержит aswitch
с разными случаями, верно?
Ответ №1:
Я не знаю ответа на вопрос, почему это не работает, но по какой-то причине typescript не может определить правильный тип свойства value. Способ решить эту проблему-использовать утверждения типа, поскольку вы знаете, что prop
расширения string
:
function myFunc<T extends string>(prop: T) {
return {
prop,
value: { a: prop, b: prop },
} as A<T>;
}
Ответ №2:
Я немного переусердствовал.
Все, что вам нужно сделать, это переоценить свою функцию.
type A<T> = {
prop: T;
value:
T extends string ? { a: T, b: T } :
T extends number ? { y: T, z: T } :
never
}
function myFunc<Prop extends string | number>(prop: Prop): A<Prop>
function myFunc<Prop extends string | number>(prop: Prop) {
return {
prop,
value: { a: prop, b: prop }
}
}
const result = myFunc('sdf').value.a // ok
const result2 = myFunc(42).value.y // ok
Я предполагаю, что у вас много switch
случаев в этой функции, в противном случае вам даже не нужен общий параметр.