我有一个与此相似的代码:
const x = 'a';
const y = 1;
const arr1 = [x, y]; // -> (string | number)[]
const arr2: [string, number] = [x, y]; // -> [string, number]
我不明白为什么TypeScript的类型推断会得到(string | number)[]
而不是[string, number]
。
我必须专门告诉TypeScript arr2: [string, number]
还是有更简单的方法?
上面的例子很简单,但是问题更令人讨厌:
function useFormField() {
const [field, setField] = useState('');
const [fieldError, setFieldError] = useState(false);
const fieldRef = useRef<HTMLInputElement>(null);
return [field, setField, fieldError, setFieldError, fieldRef];
}
类型推断:(string | boolean | React.RefObject<HTMLInputElement> | React.Dispatch<React.SetStateAction<string>> | React.Dispatch<React.SetStateAction<boolean>>)[]
要使其成为我需要的,我必须手动定义返回类型:
function useFormField(): [string, React.Dispatch<React.SetStateAction<string>>, boolean, React.Dispatch<React.SetStateAction<boolean>>, React.RefObject<HTMLInputElement>]{
// ...
}
答案 0 :(得分:1)
Typescript通常不会推断数组文字的元组。没有显式类型的元组可以通过多种方法进行推断(具有显式类型的版本也可以工作,但您可能希望避免重复)。
如果我们具有rest参数类型的类型参数,Typescript会推断出元组
function tuple<T extends any[]>(...a: T) {
return a
}
let r = tuple(1,2,3) // [number, number, number]
另一种选择,如果我们要保留数组文字语法,则使用既是数组又是单个元素元组(any | any[]
)的约束,单个元素元组将向编译器提示我们想要的一个元组,但是数组将允许该元组具有任意大小:
function tuple<T extends [any] | any[]>(a: T) {
return a
}
let r = tuple([1,2,3]) // [number, number, number]
as const
(用于TS 3.4及更高版本)3.4添加所谓的const assertion。这有几个副作用,其中之一就是推断元组。另一个是推断一个只读的元组并推断所有文字的文字类型,这可能会使此解决方案不像该函数那样普遍,但是您可以根据需要进行混合和匹配:
let r = [1,2,3] as const // [1,2,3]