【问题标题】:Nested generics in typings function类型函数中的嵌套泛型
【发布时间】:2020-06-29 18:51:06
【问题描述】:

这个问题是关于 .d.ts 作为 .js 文件的声明。

我正在尝试声明一个在泛型中具有泛型的函数,但我似乎无法正确处理。该函数本质上是一个用于对象 ({[key: string]: E}) 的 Array#forEach 函数。

我尝试了以下方法,但 VSCode 智能感知似乎无法理解对象的属性值的类型。

打字文件:

export module Util {
    export function forEach<K, T extends { [key: string]: K }>(obj: T, callbackfn: (value: K, key: string, object: T) => void): void;
}

JavaScript 调用:

if (undefined) var { Util } = require("./globals");
/** @type {{ [key:string]: number }} */
var obj = {};
Util.forEach(obj, function (value, key, object) { });

forEach的源码:

function forEach(obj, callbackfn) {
    if (!(obj instanceof Object)) throw Error("Util.forEach called on non object");
    for (var key in obj) callbackfn.call(obj, obj[key], key, obj);
}

【问题讨论】:

    标签: javascript visual-studio-code intellisense .d.ts


    【解决方案1】:

    我对您的代码没有任何问题。如您所见,在 JS 文件和 TS 文件中导入时,对象属性类型也正确显示:

    使用 Visual Studio Code 1.43.1 和 Node.js 13.11.0 测试

    我已经在这里上传了代码:https://github.com/Guerric-P/typescript-test

    编辑:

    现在我明白了你的实际问题,这是你的做法:

    export module Util {
        export function forEach<T, T1 extends keyof T, T2 extends T[keyof T]>(obj: T, callbackfn: (value: T2, key: T1, object: T) => void): void;
    }
    

    这给出了以下内容:

    如果您想详细了解为什么密钥类型是 string | number 而不是 string,请查看以下问题:Keyof inferring string | number when key is only a string

    【讨论】:

    • 在我的示例中,我将对象声明为{ [key:string]: number },因此所有值都是数字
    【解决方案2】:

    你真正想做的是:

    export function forEach<T extends object>(obj: T, callbackfn: (value: T[keyof T], key: keyof T, object: T) => void): void {
      if (!(obj instanceof Object)) throw Error("Util.forEach called on non object");
      for (var key in obj) callbackfn.call(obj, obj[key], key, obj);
    }
    
    const a = {
      test: 1,
      test2: 2,
      test3: 'me'
    };
    
    forEach(a, (value, key, obj) => {})
    

    您只需要 1 个通用参数!您可以从中推断出其余类型

    这甚至适用于更严格的类型:

    更新:添加d.ts文件:

    export module Util {
      export function forEach<T extends object>(obj: T, callbackfn: (value: T[keyof T], key: keyof T, object: T) => void): void
    }
    

    【讨论】:

    • 您的答案使用 Typescript。我正在使用 JavaScript。
    • 您需要做的是将打字稿提取到 d.ts :) 这很容易。我可以为你做这件事
    • 已将 export function forEach&lt;T, K extends T[keyof T]&gt;(obj: T, callbackfn: (value: K, key: string, object: T) =&gt; void): void; 更改为 export function forEach&lt;T extends Object&gt;(obj: T, callbackfn: (value: T[keyof T], key: string, object: T) =&gt; void): void;(如果总是使用 string,则看不到使用 key: keyof T 的意义)。
    • 它并不总是一个字符串!看看打字稿文字类型! typescriptlang.org/docs/handbook/…
    • 我使用for (var key in obj)key 的值将始终是string
    猜你喜欢
    • 2019-05-06
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    • 2019-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多