首页 > 解决方案 > TypeScript 在 Map 中保留类

问题描述

解释我需要得到什么太复杂了,让我展示一个带有一些注释的代码。
我想它会清楚得多。

abstract class Base {
    abstract getType(): string;

    static test(): string[] {
        return [];
    }
}
class Foo extends Base {    
    foo =  '123';

    getType(): string {
        return "foo";
    }

    static test(): string[] {
        return ["a", "b", "c"]
    }
}
class Bar extends Base {    
    bar =  '321';

    getType(): string {
        return "bar";
    }
    static test(): string[] {
        return ["a", "b", "c"]
    }
}

// The following map is a temporary solution just to show what I want to get
// I supposed the map has to have another type instead of "any"
const m = new Map<string, any>();
m.set("foo", Foo);
m.set("bar", Bar);

console.log(m.get('foo').test()); // << I need to have access to static functions and it works with "any" type


function func(it: Base) {
    const baseType = it.getType();

    if (m.has(baseType)) {
        const cl = m.get(baseType);

        const item = it as cl; // << error: 'cl' refers to a value, but is being used as a type here. Did you mean 'typeof cl'?
        console.log(item);
    }
}

// I know I could do it by the following way, but in this case if I will want to add a few more new classes I will have to update many palces in the code.
// I'd like just to add a new class into the map without updating the entire code.
function func2(it: Foo|Bar) { 
    const baseType = it.getType();
    console.log(baseType, it)
}


const fooInst = new Foo();
func(fooInst);
func2(fooInst);

这个代码在操场上。

我想得到什么:

标签: typescriptcasting

解决方案


具有类列表的映射或对象

在 TypeScript 中,可以使用union来实现类列表。

为了使联合与类的静态成员一起工作,您还应该使用typeof关键字

转换为基于属性的类型

为了转换为基于基础对象属性的类型,您需要使用类型保护。

类型保护

类型保护是一种检查,确保给定的参数是类型。这可以是typeof关键字,即typeof arg == "string",也可以是用户定义的类型保护;

function isArgString(arg: any): arg is string => {
    return typeof arg == "string";
}

回顾

回顾一下,使您的地图工作的方法是使用联合,并且对于您的铸造,使用类型保护:

type myUnion = typeof Foo | typeof Bar;


export const isBar = (arg: Base): arg is Bar => {
    return arg.getType() === 'bar';
}


export const isFoo = (arg: Base): arg is Foo => {
    return arg.getType() === 'foo';
}

游乐场链接


推荐阅读