gpt4 book ai didi

typescript - 使用 typescript 强制执行参数组合

转载 作者:行者123 更新时间:2023-12-05 04:25:55 28 4
gpt4 key购买 nike

我有以下代码:

enum ParamOneType {
Round,
Square,
}

interface PossibleValues {
[ParamOneType.Round]: 'a' | 'b';
[ParamOneType.Square]: 'c' | 'd';
}

const indexRound = {
a: 'whatever',
b: 'whatever',
};

const doSomething = <T extends ParamOneType>(
paramOne: T,
paramTwo: PossibleValues[T],
): void => {
switch (paramOne) {
case ParamOneType.Round: {
// Type 'PossibleValues[T]' cannot be used to index type '{ a: string; b: string; }'
const b = indexRound[paramTwo];
}
}
};

为什么我会得到错误 Type 'PossibleValues[T]' cannot be used to index type '{ a: string; b:字符串; }' 这里? Intellisense 似乎确实正确地获取了函数签名,例如我在 VSCode 中的自动完成显示:

const doSomething: <ParamOneType.Round>(paramOne: ParamOneType.Round, paramTwo: "a" | "b") => void

当调用函数时 doSomething(ParamOneType.Round, 'a')

最佳答案

对于此示例,您执行 switchparamOne ,我会远离generics , 不能是 narrowed by control flow analysis . T 总是有可能的可能是完整的 ParamOneType键入,此时有人可以调用 doSomething()使用您不期望的参数,例如 doSomething( Math.random()<0.99 ? ParamOneType.Round : ParamOneType.Square, "c") ,它有 99% 的可能性是坏的。这使得缩小通用函数内部变得棘手。这是一个已知问题,并且有多个功能请求以某种方式改进它。参见 microsoft/TypeScript#27808microsoft/TypeScript#33014获取更多信息。

相反,您可以提供 doSomething一个rest parameter其类型是 discriminated unionrest tuple types , 并立即 destructure进入两个变量paramOneparamTwo .

type DoSomethingParams =
[paramOne: ParamOneType.Round, paramTwo: "a" | "b"] |
[paramOne: ParamOneType.Square, paramTwo: "c" | "d"]

const doSomething = ([paramOne, paramTwo]: DoSomethingParams): void => { }

您可以看到调用方的行为符合预期:

doSomething(ParamOneType.Round, "a") // okay
doSomething(ParamOneType.Round, "c") // error
doSomething(ParamOneType.Square, "c") // okay
doSomething(ParamOneType.Square, "b") // error

并且由于 TypeScript 4.6 及更高版本支持 control flow analysis for destructured discriminated unions , 你可以打开 paramOne在执行和编译器会自动缩小paramTwo因此:

const doSomething = (...[paramOne, paramTwo]: DoSomethingParams): void => {
switch (paramOne) {
case ParamOneType.Round: {
const b = indexRound[paramTwo]; // okay
}
}
};

另请注意,您可以生成上面的 DoSomethingParamsPossibleValues 以编程方式键入,如下:

type DoSomethingParams = { [T in ParamOneType]:
[paramOne: T, paramTwo: PossibleValues[T]]
}[ParamOneType]

这称为分布式对象类型(在ms/TS#47109 中创造),您可以立即index into一个mapped type得到 union[paramOne: T, paramTwo: PossibleValues[T]]对于每个 TPossibleValues .

Playground link to code

关于typescript - 使用 typescript 强制执行参数组合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73139761/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com