【问题标题】:Generic types with an extends clause doesn't always get narrowed down like they should带有 extends 子句的泛型类型并不总是像应有的那样缩小范围
【发布时间】:2022-01-11 05:58:27
【问题描述】:

在这个例子中:

type MyType = 'val1' | 'val2' | 'val3';

const variable = 'val1' as MyType;

const val2 = 'val2';
const val3 = 'val3';

declare function test<U extends MyType>(...args: U[]): void;

test(val2, val3); // U successfully resolves to "val3" | "val2"

declare function test2<T, U extends T>(value: T | undefined, ...values: U[]): void;

test2(variable, val2, val3); // U gets widened to "val1" | "val2" | "val3"

testtest2U extends MyType 中。

然后我希望test2 能够将U 解析为"val3" | "val2",就像它在test 中所做的那样,但事实并非如此。

这是为什么呢?

TypeScript playground

【问题讨论】:

  • TMyTypeU 扩展 T 然后 U 扩展 MyType
  • U 在这两种情况下都扩展了MyType 那么为什么它的行为不同呢?
  • @GuerricP 在 test1 中,val2 的类型为 "val2"val3 的类型为 "val3"。在 test2 中,variable 的类型为 "val1" | "val2" | "val3"。所以在 test1 中,U 的类型可以通过val2val3 的类型来缩小范围。但是在 test2 中,T 的类型(以及通过代理还 U)被强制与variable 的类型一样宽,即"val1" | "val2" | "val3"
  • @Olian04 但是在test2 中,T 的类型被强制与变量的类型一样宽因为约束是@987654353,所以不应该这样做@ 所以它 U 可能是一个子类型。 'val1' | 'val2' 实际上扩展了 'val1' | 'val2' | 'val3'
  • @GuerricP 可能不会。以我的经验,TS 经常做这种事情。 TS团队让TS时不时偷工减料。特别是如果它可以检测到生成的类型不会在类型系统的其他地方使用。我认为 TS 认为 "val1" | "val2" | "val3" 类型对于参数列表来说已经足够好了。但是,如果预计会返回类型 U,则需要花费更多时间来解析其实际类型。

标签: typescript generics


【解决方案1】:

我相信这是类型系统偷工减料的情况。打字稿被允许不时地在类型检查上偷工减料。特别是如果它可以检测到生成的类型不会在类型系统的其他地方使用。我认为 typescript 认为 "val1" | "val2" | "val3" 类型对于参数列表来说已经足够好了。 但是,假设我们将test2 的返回类型从void 更改为U。然后,由于预计会返回类型 U 并可能在 typescript 的其他地方使用,因此编译器将需要花费更多时间来解析 U 的实际/最窄类型。

type MyType = 'val1' | 'val2' | 'val3';

const variable = 'val1' as MyType;

const val2 = 'val2';
const val3 = 'val3';

declare function test2<T, U extends T>(value: T | undefined, ...values: U[]): void;

test2(variable, val2, val3); // U gets widened to "val1" | "val2" | "val3"

declare function test3<T, U extends T>(value: T | undefined, ...values: U[]): U;

test3(variable, val2, val3); // U successfully resolves to "val3" | "val2"

playground

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-20
    • 2013-08-13
    相关资源
    最近更新 更多