В TypeScript нет внутренней связи между строковыми литеральными типами (например, "IMyType"
) и именами именованных типов (например, IMyType
). Строковые литеральные типы представляют фактические строковые значения, которые существуют во время выполнения, в то время как имена типов соответствуют аспектам системы типов stati c, которая полностью стерта из испущенного JavaScript.
Кроме того, система типов структурная , а не номинальная, поэтому имена типов на самом деле не имеют большого значения. Если я объявлю
type IYourType = IMyType;
, то IYourType
и IMyType
- это просто два разных имени для одного и того же типа. И поэтому, если SomeAbsClass.getSomething<IYourType>("IYourType");
успешен, тогда SomeAbsClass.getSomething<IMyType>("IYourType");
должен также успешно.
Нет принципиального способа заставить систему типов решить, что одно имя является более "каноническим", чем другое, так что SomeAbsClass.getSomething<IMyType>("IMyType");
завершается успешно и SomeAbsClass.getSomething<IMyType>("IYourType");
завершается неудачей автоматически.
Поскольку это не происходит автоматически, самое близкое, что я могу себе представить - это * ручное создание типа, представляющего желаемое отображение между строковыми литералами и типами, например как:
interface TypeMapping {
IMyType: IMyType;
Date: Date;
string: string;
boolean: boolean;
// add whatever you want
}
и затем использовать это отображение в вашем определении getSomething()
, например,
declare const SomeAbsClass: {
getSomething<T>(x: {
[K in keyof TypeMapping]: TypeMapping[K] extends T ? K : never }[keyof TypeMapping]
): void;
}
И вы называете это следующим образом (убедитесь, что явно указали generi c введите параметр при этом):
SomeAbsClass.getSomething<IMyType>("IMyType"); // okay
SomeAbsClass.getSomething<IMyType>("IYourType"); // error
Это работает, насколько это возможно. Подходит ли он для вашего варианта использования - это другая история.
Хорошо, надеюсь, это поможет; удачи!
Детская площадка ссылка на код