Tell method's parameter to accept only <T> as exact string

|▌冷眼眸甩不掉的悲伤 提交于 2020-04-30 07:15:08

问题


I'd like to have something like this:

SomeAbsClass.getSomething<IMyType>("IMyType");

So, how to I code getSomething's parameter so it'll only accept the exact "IMyType" as string?

There's something to do with Conditional types, in the same vein as this, but I can't figure it out.


回答1:


There's no inherent relationship in TypeScript between string literal types (like "IMyType") and the names of named types (like IMyType). String literal types represent actual string values which exist at runtime, while type names respresent aspects of the static type system which is completely erased from the emitted JavaScript.

Furthermore, the type system is structural, not nominal, so the names of types don't really matter much. If I declare

type IYourType = IMyType;

then IYourType and IMyType are just two different names for the same type. And therefore if SomeAbsClass.getSomething<IYourType>("IYourType"); succeeds, then SomeAbsClass.getSomething<IMyType>("IYourType"); should also succeed.

There's no principled way to force the type system to decide that one name is more "canonical" than another, so that SomeAbsClass.getSomething<IMyType>("IMyType"); succeeds and SomeAbsClass.getSomething<IMyType>("IYourType"); fails automatically.


Since this doesn't happen automatically, the closest I can imagine getting here is for you to manually build up a type representing the desired mapping between string literals and types, such as:

interface TypeMapping {
    IMyType: IMyType;
    Date: Date;
    string: string;
    boolean: boolean;
    // add whatever you want
}

and then use that mapping in your definition of getSomething(), like this

declare const SomeAbsClass: {
    getSomething<T>(x: {
        [K in keyof TypeMapping]: TypeMapping[K] extends T ? K : never }[keyof TypeMapping]
    ): void;
}

And you call it like this (making sure to explicitly specify the generic type parameter when you do so):

SomeAbsClass.getSomething<IMyType>("IMyType"); // okay
SomeAbsClass.getSomething<IMyType>("IYourType"); // error

That works as far as it goes. Whether it fits your use case is another story.


Okay, hope that helps; good luck!

Playground link to code



来源:https://stackoverflow.com/questions/60973387/tell-methods-parameter-to-accept-only-t-as-exact-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!