代码之家  ›  专栏  ›  技术社区  ›  Noob

Typescript中使用泛型的类型推理?

  •  0
  • Noob  · 技术社区  · 2 年前

    我有两个签名略有不同的函数:

    const getValue = <TObj>(obj: TObj, key: keyof TObj) => {
      return obj[key];
    };
    
    
    const getValueMultiple = <TObj, TKey extends keyof TObj>(obj: TObj, key: TKey) => {
      return obj[key];
    };
    
    const result1 = getValue({ a: 1, b: 'some-text', c: true }, 'c');
    // result1: string | number | boolean
    
    const result2 = getValueMultiple({ a: 1, b: 'some-text', c: true }, 'c');
    //const result2: boolean
    

    我不明白为什么在第一种情况下result1是类型 string|number|boolean (我希望它是布尔型的),以及为什么在第二种情况下result2类型会按预期推断。

    如有帮助或参考相关文件,我将不胜感激。

    1 回复  |  直到 2 年前
        1
  •  1
  •   whygee    2 年前

    根据我的理解,以下是TypeScript的看法

    const getValue = <TObj>(obj: TObj, key: keyof TObj) => {
      return obj[key];
    };
    
    // equivalent to
    
    const getValue = <TObj>(obj: TObj, key: keyof TObj): TObj[keyof TObj] => {
      return obj[key];
    };
    
    const getValueMultiple = <TObj, TKey extends keyof TObj>(obj: TObj, key: TKey) => {
      return obj[key];
    };
    
    // equivalent to 
    
    const getValueMultiple = <TObj, TKey extends keyof TObj>(obj: TObj, key: TKey): TObj[TKey] => {
      return obj[key];
    };
    
    

    一开始你可能认为没有区别,但实际上是有区别的;

    让我们把TObj取为{a:数字,b:字符串,c:布尔值}

    TObj[keyof TObj] = TObj["a" | "b" | "c" ] = number | string | boolean
    

    然而,关于TObj[TKey],因为TKey正是“a”|“b”|“c”中的一个,并且TypeScript通过泛型参数知道它是哪一个 TKey extends keyof TObj ,您会得到一个精确的返回类型。