justcodin
justcodin

Reputation: 1013

Typescript - Is there a way to apply a type to a variable via a constant?

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

Answers (3)

Alex Wayne
Alex Wayne

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)

Playground

Upvotes: 1

justcodin
justcodin

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

Sebastian Speitel
Sebastian Speitel

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

Related Questions