Вложенные дженерики в функции набора текста - PullRequest
2 голосов
/ 18 марта 2020

Этот вопрос касается .d.ts как объявлений для .js файлов.

Я пытаюсь объявить функцию, у которой есть generi c внутри generi c, но я не могу кажется, понял это правильно. По сути, эта функция является Array#forEach функцией для объектов ({[key: string]: E}).

Я пробовал следующее, но intellisense 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);
}

Ответы [ 2 ]

2 голосов
/ 21 марта 2020

У меня нет проблем с вашим кодом. Как видите, типы свойств объекта отображаются корректно при импорте в файл JS, а также в файл TS:

enter image description here

Протестировано с Visual Код студии 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;
}

Что дает следующее:

enter image description here enter image description here

Если вы хотите получить более подробную информацию о том, почему тип ключа string | number вместо string, проверьте этот вопрос: Keyof inferring string | число, когда ключом является только строка

1 голос
/ 27 марта 2020

То, что вы действительно хотите сделать, это:

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 параметр c! Из него можно вывести остальные типы enter image description here

Это работает даже с более строгими типами:

enter image description here

Обновление : добавить 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
}
...