gpt4 book ai didi

typescript - 使用泛型缩小类型

转载 作者:行者123 更新时间:2023-12-04 07:13:54 25 4
gpt4 key购买 nike

我想在一个函数中链接 2 个泛型类型,并通过检查其中一个类型对这两种类型使用缩小。这样做的正确方法是什么?

type A = 'A';
type B = 'B';

type AB = A | B

type ComplexType<T> = {value: T}

const f = (next: ComplexType<A>) => {}

const builder = <T extends AB>(value: T) => (next: ComplexType<T>) => {
if (value === 'A') {
f(next) // expect next is ComplexType<A> but got error
}
}

最佳答案

目前没有办法缩小像 T 这样的类型参数。通过检查像 value 这样的值.可能是 value === "A"是真的,但这并不意味着 T"A" .毕竟,也许value类型为 "A" | "B" ,比如说通过传入一个表达式,其中编译器推断完整的联合类型:

builder(Math.random() <= 0.999 ? "A" : "B") // no error
这里有 99.9% 的机会你通过了 "A"但你仍然有可能通过 "B" .编译器推断 T"A" | "B" .因此 next参数的类型为 ComplexType<"A" | "B"> .所以当你调用这个时没有编译器错误:
builder(Math.random() <= 0.999 ? "A" : "B")({ value: "B" }); // no error
这意味着编译器在技术上是正确的 f(next)可能是错误的。

GitHub 中存在多个现有问题,要求支持缩小泛型函数体内的类型参数。与您的代码最相关的可能是 microsoft/TypeScript#27808 .这要求某种方式告诉编译器 T应该是 "A""B"而不是 "A" | "B" .也许语法类似于 T extends_oneof [A, B](T extends A) | (T extends B)或者完全不同的东西。那么也许当你测试时 value === "A"编译器会得出结论 T extends A ,一切都会好起来的。唉,目前没有这样的支持。

现在你只需要解决它。如果你相当有信心,没有人会调用你的 builder()错误地,你可以只使用 type assertion并继续:
const builder = <T extends AB>(value: T) => (next: ComplexType<T>) => {
if (value === 'A') {
f(next as ComplexType<A>) // okay
}
}

如果你真的需要用 builder() 来防止调用者做错事您可以制作越来越复杂的调用签名,相当于模拟“扩展其中之一”约束,例如:
type NoneOf<T, U extends any[]> =
[T] extends [U[number]] ? never : T;
type OneOf<T, U extends any[]> =
U extends [infer F, ...infer R] ? [T] extends [F] ? NoneOf<T, R> : OneOf<T, R> : never;

const builder = <T extends "A" | "B">(
value: T & OneOf<T, ["A", "B"]>
) => (next: ComplexType<T>) => {
if (value === 'A') {
f(next as ComplexType<"A">)
}
}

builder(Math.random() <= 0.999 ? "A" : "B"); // error now
builder2("A") // okay
builder2("B") // okay
但当然编译器不能在 builder 的主体内遵循它无论如何(通用条件类型很难处理)所以你仍然需要类型断言。就我个人而言,我只会将您的原始签名与类型断言一起使用,并且如果您在实践中遇到无效调用,则只会重新访问任何更复杂的东西。
Playground link to code

关于typescript - 使用泛型缩小类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68897217/

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