TypeScript实际上并不直接支持“穷举数组”。您可以引导编译器检查这一点,但这对您来说可能有点混乱。一个绊脚石是缺少
部分类型参数推断
(按照
microsoft/TypeScript#26242
).以下是我的解决方案:
type Furniture = 'chair' | 'table' | 'lamp' | 'ottoman';
type AtLeastOne<T> = [T, ...T[]];
const exhaustiveStringTuple = <T extends string>() =>
<L extends AtLeastOne<T>>(
...x: L extends any ? (
Exclude<T, L[number]> extends never ?
L :
Exclude<T, L[number]>[]
) : never
) => x;
const missingFurniture = exhaustiveStringTuple<Furniture>()('chair', 'table', 'lamp');
// error, Argument of type '"chair"' is not assignable to parameter of type '"ottoman"'
const extraFurniture = exhaustiveStringTuple<Furniture>()(
'chair', 'table', 'lamp', 'ottoman', 'bidet');
// error, "bidet" is not assignable to a parameter of type 'Furniture'
const furniture = exhaustiveStringTuple<Furniture>()('chair', 'table', 'lamp', 'ottoman');
// okay
如你所见,
exhaustiveStringTuple
是一个
curried
函数,其唯一目的是获取手动指定的类型参数
T
然后返回一个新函数,该函数接受类型受约束的参数
T
但根据电话推断。(如果我们有适当的部分类型参数推断,可以消除currying。)就你而言,
T
将指定为
Furniture
.如果你只关心
exhaustiveStringTuple<Furniture>()
,然后你可以用它来代替:
const furnitureTuple =
<L extends AtLeastOne<Furniture>>(
...x: L extends any ? (
Exclude<Furniture, L[number]> extends never ? L : Exclude<Furniture, L[number]>[]
) : never
) => x;
Playground link to code