gpt4 book ai didi

javascript - typescript:从条件类型派生类型

转载 作者:行者123 更新时间:2023-12-05 00:37:57 27 4
gpt4 key购买 nike

typescript 支持 Conditional Types .
但是当我尝试设置 op 的值时作为字符串,它给了我错误,我如何检查类型和赋值?

export const t = <IsMulti extends boolean = false>(): void => {
const value = 'test';
type S = string;
type D = IsMulti extends true ? S[] : S;
const op: D = value;
console.log(op);
};
错误: Type 'string' is not assignable to type 'D'.我什至尝试添加相同类型的参数 IsMulti并基于它添加检查
export const t = <IsMulti extends boolean = false>(isMulti: IsMulti): void => {
const value = 'test';
type S = string;
type D = IsMulti extends true ? S[] : S;
if (!isMulti) {
const op: D = value;
console.log(op);
}
};
它仍然给出同样的错误。
enter image description here

最佳答案

评价conditional types这取决于尚未指定的 generic类型参数通常由编译器延迟;如果编译器不确切知道 IsMulti是,那么它不知道到底是什么IsMulti extends true ? S[] : S是,所以它不会让你分配一个类型的值(比如)S到那个条件类型,因为它无法验证这是一个类型安全的操作。编译器甚至没有真正尝试评估这种条件类型。它使它们成为不透明的东西,几乎没有任何东西可以分配给它。
对于您的第一个示例,这是编译器所需的行为;分配 string 确实不安全至op因为D很可能是string[] .没有什么能阻止某人调用 t<true>() .只是因为IsMulti有一个 defaultfalse不代表是false .

对于您的第二个示例,这是当前 TypeScript 的限制。编译器不能使用 control flow analysis缩小类型参数。因此它无法验证可分配性参见 microsoft/TypeScript#33912详情。
当您查看 if (!isMulti) ,编译器缩小 isMulti 的类型在 IsMulti 的后续代码块内只需输入 false :

export const t = <IsMulti extends boolean = false>(isMulti: IsMulti): void => {
if (!isMulti) {
// isMulti is now known to be false
const fls: false = isMulti; // okay
const tru: true = isMulti; // error
}
};
但它并没有缩小类型参数 IsMulti本身。通常这也是编译器期望的行为,因为 IsMulti extends boolean表示 IsMulti实际上可能是完整的 union boolean (而不是只是 true 或只是 false ),所以检查类型的值 IsMulti对缩小 IsMulti 没有用处本身。所有你能说的 if (!isMulti)IsMulti不能只是 true ...但它可能仍然是 boolean .当然如果是 boolean ,然后 D , 一个 distributive conditional type将成为联合 S[] | S ,并且您应该被允许分配 string到那个。所以没有合理的方法来分配 "test"op应该是不安全的。
然而,编译器无法验证这一点。它固执地离开 IsMulti一个人,不会让你分配任何东西给 D因为它推迟了评估。如果有一些支持的方法来缩小类型参数,或者验证泛型条件类型的可分配性,那就太好了。目前,真的没有。上面链接的 GitHub 问题是一个改进此问题的功能请求,并且有许多相关请求可能会有所帮助(例如, microsoft/TypeScript#27808 可以将 IsMulti 限制为完全 true 或完全 false ,大概然后 if (!isMulti) 会将以前的通用类型 IsMulti 缩小到特定类型 false ,并且 D 将被急切地评估)。您可以解决这些问题并给他们一个 👍,但短期内这里会发生任何事情并不明显。

相反,在这种你比编译器更了解类型的情况下,你可以使用 type assertion抑制可分配性错误:
export const t = <IsMulti extends boolean = false>(isMulti: IsMulti): void => {
const value = 'test';
type S = string;
type D = IsMulti extends true ? S[] : S;
if (!isMulti) {
const op = value as D; // okay
console.log(op);
}
};
通过写 value as D你告诉编译器你知道 value绝对是 D 类型,即使编译器不能。这允许程序无错误地编译。请注意,这不是魔术,并且通过执行类型断言,您可以从编译器中承担一些类型安全的责任。如果你犯了一个错误或对编译器撒谎,它不能总是捕获它:
if (!isMulti) {
const op = ["oopsie"] as D; // still okay
console.log(op);
}
所以要小心!
Playground link to code

关于javascript - typescript:从条件类型派生类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71018294/

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