Reputation: 1013
This is what I expect (This is not valid TS) :
const type1 = "number";
let myVariable1 : typeof<type1> = 12;
let type2 = "string" as const;
let myVariable2 : typeof<type2> = "foo";
Is there a way to apply a type like this in TypeScript ?
Upvotes: 1
Views: 358
Reputation: 187034
I think the simplest way to support this is to create an interface that maps your type names to actual types. Then all you have to look them up:
interface LookupType {
number: number
string: string
boolean: boolean
"number[]": number[]
person: Person
}
const type1 = "number";
let myVariable1: LookupType[typeof type1] = 12;
let type2 = "string" as const;
let myVariable2: LookupType[typeof type2] = "foo";
let type3 = 'number[]' as const
let myVariable3: LookupType[typeof type3] = [1,2,3]
This works because the keys of this interface are strings, even if that string happens to be the same name as the type it references. This would be an easier list to maintain than a set of branching conditionals.
It also has the added benefit of easy type checking for unsupported types
let doesntExist = 'badTypeName' as const
let badVar: LookupType[typeof doesntExist] = 123
// Property 'badTypeName' does not exist on type 'LookupType'.(2339)
Upvotes: 1
Reputation: 1013
This is inspired by Sebastian Speitel's answer :
We can also use type checking with personal type :
type Person = { name : string, age : number };
type typeByString<T> = T extends "Person" ? Person : number;
const a: typeByString<"Person"> = {name : "Foo", age : 20};
const b: typeByString<"other"> = 23;
It's also possible to pick string type from an array of strings :
type typeByString<T> = T extends 'number' ? number : T extends 'string' ? string : T extends 'boolean' ? boolean : T extends 'null' ? null : T extends 'number[]' ? number[] : T extends 'string[]' ? string[] : T extends 'boolean[]' ? boolean[] : any;
const myTypes = ["string", "null"] as const;
const selected = myTypes[0];
const c : typeByString<typeof selected> = "cool";
const d : typeByString<typeof myTypes[1]> = null;
Upvotes: 1
Reputation: 7346
You can use a conditional type:
type typeByString<T> = T extends "number" ? number : T extends "string" ? string : any;
type str = typeByString<"string">; // str is string
type num = typeByString<"number">; // num is number
Upvotes: 2