2017-09-15 46 views
1

如何使打字稿得出的assertTypof一般的參數基礎上,expectedType如何從它的字符串表示獲得式

即價值,我想下面的應用功能,而無需指定number兩次

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 

回答

1

您可以編碼字符串 - >在接口類型映射,並使用indexed access type operator作爲返回類型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 
+0

這是一個很好的答案,但是你沒有使用映射類型(這可以通過在索引簽名中使用'in'關鍵字來識別,就像'{[keyof T]中的']: string}');你正在使用[索引訪問操作符](https://www.typescriptlang.org/docs/handbook/advanced-types.html#index-types)。 – jcalz

+0

你是對的,我解決了答案,謝謝 – artem

+0

在這裏實現你的想法https://github.com/BjornMelgaard/ramda-asserters/blob/master/src/assertTypeof.ts – bjornmelgaard