2017-09-15 47 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