srghma
srghma

Reputation: 5323

How to get type from its string representation

How to to make typescript derive generic argument of assertTypof based on value of expectedType

Namely, I want to apply function below without specifying number two times

playable example

type TypeLiteral = "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"

// I know its bad to return generic, but dont know how to make without it
function assertTypeof<T>(expectedType: TypeLiteral, target: any): T {
    const actualType = typeof target
    if (actualType === expectedType) return target

    throw new Error(`Expected ${expectedType}, but got ${actualType}`)
}


const n1 = assertTypeof<number>('number', 1) // fine
const n2 = assertTypeof<number>('number', {}) // error

Upvotes: 4

Views: 1761

Answers (1)

artem
artem

Reputation: 51579

You can encode string -> type mapping in an interface, and use indexed access type operator as return type for assertTypeof:

interface TypeMap {
    string: string,
    number: number,
    boolean: boolean,
    symbol: Symbol,
    undefined: undefined,
    object: object,
    function: Function
};

function assertTypeof<N extends keyof TypeMap>(expectedType: N, target: any)
 : TypeMap[N] {
    const actualType = typeof target
    if (actualType === expectedType) return target

    throw new Error(`Expected ${expectedType}, but got ${actualType}`)
}

const n1 = assertTypeof('number', 1) // fine
const n2 = assertTypeof('number', {}) // runtime error

Upvotes: 3

Related Questions