我正在尝试编写一个函数,该函数有条件地推断作为联合的通用输入参数的类型。当我将输入类型设置为条件时,它会抛出一个错误,表明它推断输入必须是联合中每个值的数组,而不是联合中任何值的数组。如果没有条件类型,它可以正确推断输入可以是联合中任何值的数组:
type StringUnion = 'a' | 'b' | 'c'
const a: StringUnion[] = ['a']
console.log(a)
function basicTest<T>(props: { data: T[] }): T {
return props.data[0];
}
const basicResult = basicTest({ data: a }) // No error
function extendsTest<T extends string>(props: { data: T[] }): T {
return props.data[0];
}
const extendsResult = extendsTest({ data: a }) // No error
function ternaryTest<T>(props: { data: T extends string ? T[] : { inner: T[] } }): T {
if ('inner' in props.data) {
return props.data.inner[0];
}
return props.data[0];
}
const ternaryResult = ternaryTest({ data: a }) // Error
// Type 'StringUnion[]' is not assignable to type '"a"[] | "b"[] | "c"[]'.
// Type 'StringUnion[]' is not assignable to type '"a"[]'.
// Type 'StringUnion' is not assignable to type '"a"'.
// Type '"b"' is not assignable to type '"a"'.ts(2322)
//
// test.ts(16, 34): The expected type comes from property 'data' which is declared here on type '{ data: "a"[] | "b"[] | "c"[]; }'
使用条件类型时如何避免这种类型错误?
问题在于联合类型的元素正在被映射(我认为这不是一个正确的术语)来推断类型参数,给你
"a"[] | "b"[] | "c"[]
而不是StringUnion[]
。
您可以通过将
[]
放在 T
和 string
周围来防止这种情况发生:
function ternaryTest<T>(props: { data: [T] extends [string] ? T[] : { inner: T[] } }): T {
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^−−−−−−−−−^^^^^^^^
if ('inner' in props.data) {
return props.data.inner[0];
}
return props.data[0];
}