指定Typescript泛型类型中联合类型的独占联接

kqlmhetl  于 2023-08-08  发布在  TypeScript
关注(0)|答案(1)|浏览(103)

是否可以指定一个泛型类型,它是两个可能的联合类型之一,但不能包含来自任何一个类型的非重叠元素?
我想做的是

type TrueFalseType = "true" | "false"
  type ABType = "A" | "B"
  
  const myFunction = <T extends ABType | TrueFalseType>(values: Array<T>) => {
    console.log(values)
  }
  
  myFunction(["A", "B"]) // should be allowed
  myFunction(["true", "false"]) // should be allowed
  myFunction(["A", "false"]) // should be compile error

字符串
这没有按预期工作,因为最后一行正在编译,而我希望它是一个错误。如何更改泛型类型定义,使其只允许ABTypeTrueFalseType类型T,而不允许两者中的元素?

kmpatx3s

kmpatx3s1#

最直接的方法是放弃generics,只让values成为您想要支持的两种不同数组类型的并集:

const myFunction = (values: ABType[] | TrueFalseType[]) => {
  console.log(values)
}

myFunction(["A", "B"]) // okay
myFunction(["true", "false"]) // okay
myFunction(["A", "false"]) // error

字符串
由于["A", "false"]既不是ABType[],也不是TrueFalseType[],因此它被拒绝。
如果出于某种原因你需要泛型,你可能仍然应该用values的类型来表达它,并将你的类型参数约束为相同的数组类型的联合:

const myFunction = <U extends ABType[] | TrueFalseType[]>(values: U) => {
  type T = U[number];
  console.log(values)
}


这里我将类型参数命名为U,只是为了表明它与您的T不同,T是数组 * 元素 * 类型。如果需要计算,可以通过indexing intoUnumber来完成(因为用数字键索引数组会产生数组元素)。即type T = U[number]
对于调用者而言,其行为相同:

myFunction(["A", "B"]) // okay
myFunction(["true", "false"]) // okay
myFunction(["A", "false"]) // error


Playground代码链接

相关问题