繁体   English   中英

Typescript:根据generics推断

[英]Typescript: Infer based on generics

arg1放置类型保护时,我希望自动推断arg2 ,但事实并非如此。

有人知道为什么这不起作用吗? 什么是最好的选择? 非常感谢!

您可以在此处查看实际使用的类型。 只需 hover over arg2即可查看推断的类型。

function example<T extends 'foo' | 'bar'>(
  arg1: T, 
  arg2: T extends 'foo' ? string : number
) {
  if (arg1 === 'foo') {
    arg2 // should be string?
  }

  if (arg1 === 'bar') {
    arg2 // should be number?
  }
}

但是,调用 function 确实正确应用了第二种 arg 类型:

在此处输入图像描述

在此处输入图像描述

这是另一个使用基于 generics 的类型化 object 的示例:

type Test <T extends boolean> = {
  multiple: T;
  value: T extends true ? string : number;
};

// this doesn't work?
function test <T extends boolean>(a: Test<T>) {
  if (a.multiple) {
    a.value // string | number?
  }else{
    a.value // string | number?
  }
}

// this works!
function test2 (a: Test<true> | Test<false>) {
  if (a.multiple) {
    a.value // is string
  }else{
    a.value // is number
  }
}

游乐场

我使用这两种解决方案来获得有条件的 arguments:

解决方案 1(推荐) :对 arguments 使用 object

type Args = { arg1: 'foo'; arg2: string } | { arg1: 'bar'; arg2: number };
function example(args: Args): void {
  if (args.arg1 === 'foo') {
    args.arg2; // It's string
  }
  if (args.arg1 === 'bar') {
    args.arg2; // It's number
  }
}

解决方案 2 :使用 arguments object

type Args = ['foo', string] | ['bar', number];
function example(...args: Args): void {
  if (args[0] === 'foo') {
    args[1]; // It's string
  }
  if (args[0] === 'bar') {
    args[1]; // It's number
  }
}

请考虑这个片段:

const k = 'foo' as 'foo' | 'bar'

example(k, 'abc') // compiles ok
example(k, 1) // compiles ok

arg2arg1不紧密耦合。 当您使用文字字符串调用example时: 'foo''bar' as arg1 Typescript 可以限制arg1的类型并推断arg2的确切类型。 但一般情况下这是不可能的。

作为一种可能的解决方法,您可以限制example的 args,如下所示:

function example2(...args: ['foo', string] | ['bar', number]) {
  if (args[0] === 'foo') {
    const s = args[1] // string
  }

  if (args[0] === 'bar') {
    const n = args[1] // number
  }
}
example2('foo', '') // ok
example2('bar', 0) // ok
example('foo', 0) // error
example2(k, 'abc') // error
example2(k, 1) // error

操场

type Test<T extends boolean>的情况非常相似。 类型的定义并没有严格限制足够的可能值。 例如:

const v1: Test<boolean> = {
  multiple: true,
  value: 'a'
}

const v2: Test<boolean> = {
  multiple: true,
  value: 1
}

使用Test<true> | Test<false> Test<true> | Test<false>使用文字类型并限制一组可能的值。

操场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM