19

我写了一个小函数来更好地处理类型。

function evaluate(variable: any, type: string): any {
    switch (type)
    {
        case 'string': return String(variable);
        case 'number': return isNumber(variable) ? Number(variable) : -1;
        case 'boolean': {
            if (typeof variable === 'boolean')
                return variable;

            if (typeof variable === 'string')
                return (<string>variable).toLowerCase() === 'true';

            if (typeof variable === 'number')
                return variable !== 0;

            return false;
        }
        default: return null;
    }
}

function isNumber(n: any): boolean {
    return !isNaN(parseFloat(n)) && isFinite(n);
}

我尝试使用泛型,但不知道如何从泛型参数中获取类型。这是可能的?

4

2 回答 2

19

typeof是一个 JavaScript 运算符。它可以在运行时用于获取 JavaScript 知道的类型。泛型是一个 TypeScript 概念,有助于检查代码的正确性,但在编译输出中不存在。所以简短的回答是否定的,这是不可能的。

但你可以这样做:

class Holder<T> {
    value: T;
    constructor(value: T) {
        this.value = value;
    }
    typeof(): string {
        return typeof this.value;       
    }
}

试试看

这是有效的,因为我正在对 Holder 内部的值进行操作,而不是对 Holder 本身进行操作。

于 2013-08-13T18:30:45.757 回答
19

您不能消除type字符串,但可以通过添加重载使您的函数在类型方面更加智能和可用:

function evaluate(variable: any, type: 'string'): string;
function evaluate(variable: any, type: 'number'): number;
function evaluate(variable: any, type: 'boolean'): boolean;
function evaluate(variable: any, type: string): unknown {
    ...
    default: throw Error('unknown type');
}
const myBool = evaluate('TRUE', 'boolean'); // myBool: boolean
const myNumber = evaluate('91823', 'number'); // myBool: boolean
evaluate('91823', 'qwejrk' as any); // RUNTIME ERROR (violated types)

const mysteryType = 'number' as 'boolean' | 'number';
const myMystery = evaluate('91823', mysteryType); // COMPILER ERROR, no overload matches.

游乐场链接

请注意,不再有 null 情况,因为无法知道未知string类型是否实际上可能包含有效值,例如'number'在编译时。

这对大多数人来说已经足够了。


然而...

请注意,mysteryType 联合不起作用。如果出于某种原因你真的真的很想让它工作,你可以使用条件类型来代替:

function evaluate<T extends string>(variable: any, type: T):
    T extends 'string' ? string :
    T extends 'number' ? number :
    T extends 'boolean' ? boolean :
    never;
function evaluate(variable: any, type: string): unknown {
    ...
    default: throw Error('unknown type');
}
const mysteryType = 'number' as 'boolean' | 'number';
const myMystery = evaluate('91823', mysteryType); // myMystery: number | boolean

游乐场链接


此外,如果您在 Google 上搜索了这个问题并且想知道如何从 获取TMyClass<T>这也是可能的:

class MyClass<T> {}

type GetMyClassT<C extends MyClass<any>> = C extends MyClass<infer T> ? T : unknown;
const myInstance = new MyClass<"hello">();
let x: GetMyClassT<typeof myInstance>; // x: "hello"

游乐场链接

于 2020-07-04T19:17:53.777 回答