Как определить тип аргумента функции в зависимости от строкового аргумента в Typescript? - PullRequest
0 голосов
/ 26 марта 2020

У меня есть существующая функция в Javascript коде, для которой я пытаюсь написать файл определения типа для строгой проверки типов. Он используется так:

createElement("a", {href: "www.example.com"});

В проекте используются пользовательские элементы html. Первый аргумент - это строка с тегом, и, как вы можете видеть, тип второго аргумента зависит от строкового тега, поскольку он должен быть картой атрибута-значения, соответствующей тому, что ожидает тег.

Я пытаюсь что-то вроде этого, но это не работает.

type Tag<T> = string;
const stringTag: Tag<string> = "IamString";
const numberTag: Tag<number> = "IamNumber";

function doStuff<T>(
    tag: Tag<T>,
    content: T
): void {
    console.log(tag, content);
}

doStuff(stringTag, "IshouldBeString");
doStuff(numberTag, "IshouldBeNumber"); // Should be WRONG
doStuff(numberTag, 10); // CORRECT

Он жалуется на неиспользуемый аргумент "T" и не жалуется на неправильный строковый параметр с numberTag. Если я использую существующий тип generi c, например Array<T> вместо Tag<T>, doStuff корректно ограничивает второй аргумент.

Я пытаюсь сохранить существующий API (тег строкового типа), но мог бы рассмотреть возможность его изменения.

Спасибо.

1 Ответ

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

Единственный способ, с помощью которого я могу думать об этом, - это «строковые литеральные типы» и условные типы, так что вам придется вручную прописать все эти определения типов.

type TagType = "a" | "button";
type Tag<T extends TagType> =
    T extends "a" ? AType :
    T extends "button" ? ButtonType : never;

interface AType {
    href: string;
}

interface ButtonType {
    onClick: () => void
}

function doStuff<T extends TagType>(tag: T, content: Tag<T>) {
    console.log(tag, content)
}

doStuff("a", { href: "" }); // CORRECT
doStuff("button", { href: "" }); // WRONG
doStuff("button", { onClick: () => {} }); // CORRECT
...