Hen*_*Jan 6 tuples type-safety typescript typescript-generics
我有一个具有泛型的函数,它是 1 个元素的元组或 2 个元素的元组。
我想确保函数中使用的所有属性都使用相同长度的元组。
type TypeA = [string] // Tuple of 1 element
type TypeB = [string, string] // Tuple of 2 elements
type Header = TypeA | TypeB
interface SomeObject<H extends Header> {
prop1: H
prop2: H
}
function useHeader<H extends Header>(someObject:SomeObject<H>) {
// do something
}
useHeader({
prop1: ["tuple of 1 element"],
prop2: [
"tuple of",
"2 elements"
] // <-- I want an error here, because prop1 and prop2 use diffrent tuples
})
Run Code Online (Sandbox Code Playgroud)
我注意到,当我更改TypeA为number和TypeBtostring时,当我混合数字和字符串时,Typescript 会出错。
当使用不同长度的元组时,是否可以使 Typescript 生成错误?
考虑这种方法:
type TypeA = [string] // Tuple of 1 element
type TypeB = [string, string] // Tuple of 2 elements
type Header = TypeA | TypeB
interface SomeObject<H extends Header> {
prop1: H
prop2: H & {} // <------- CHANGE IS HERE
}
function useHeader<H extends Header>(someObject: SomeObject<H>) {
// do something
}
useHeader({
prop1: ["tuple of 1 element"],
prop2: [
"tuple of",
"2 elements"
] // <-- I want an error here, because prop1 and prop2 use diffrent tuples
})
Run Code Online (Sandbox Code Playgroud)
该行的H & {}意思是“降低推理优先级”。换句话说,TS 将首先推断Hfor prop1,然后才推断第二个prop2,而不是同时推断。
虽然这不是记录在案的功能,但 Ryan Cavanaugh(TypeScript 团队的开发负责人)在此表示,它是“......设计......”(带有强调)并且“......可能会在可预见的未来发挥作用。 ”
您可以在我的博客中找到更多未记录的功能。这个答案中提供了这个特殊的技巧
没有未记录的技巧:
type TypeA = [string] // Tuple of 1 element
type TypeB = [string, string] // Tuple of 2 elements
type Header = TypeA | TypeB
type IsLengthEqual<T extends any[], U extends any[]> = U extends { length: T['length'] } ? U : never
interface SomeObject<H extends Header, H2 extends Header> {
prop1: H
prop2: IsLengthEqual<H, H2>
}
function useHeader<H extends Header, H2 extends Header>(someObject: SomeObject<H, H2>) {
// do something
}
useHeader({
prop1: ["tuple of 1 element"],
prop2: [
"tuple of",
'dfg'
] // error
})
Run Code Online (Sandbox Code Playgroud)
并且只有一个通用的
type TypeA = [string] // Tuple of 1 element
type TypeB = [string, string] // Tuple of 2 elements
type Header = TypeA | TypeB
interface SomeObject<H extends Header> {
prop1: H
prop2: { [Prop in keyof H]: string }
}
function useHeader<H extends Header>(someObject: SomeObject<[...H]>) {
// do something
}
useHeader({
prop1: ["tuple of 1 element"],
prop2: [
"tuple of",
'dfg'
] // error
})
Run Code Online (Sandbox Code Playgroud)