【问题标题】:Strongly typed discriminated deserializer强类型可区分反序列化器
【发布时间】:2018-06-13 16:38:03
【问题描述】:

我希望就我是否/如何利用 TypeScript 来强键入一个像这样工作的函数获得一些建议:

function createDeserializer(typeDeserializers) {
    return (data) => {
        const deserializer = typeDeserializers[data.__type];
        return deserializer(data);
    }
}

我希望能够做这样的事情:

const personDeserializer = createDeserializer({
    'employee': (data) => new Employee(data),
    'customer': (data) => new Customer(data)
});

const person1 = personDeserializer({ __type: 'employee', ... });
const person2 = personDeserializer({ __type: 'customer', ... });

// Here TypeScript knows that person1 is an 'Employee' instance, and person2 is a 'Customer' instance. 

我想我需要对 typeDeserializers 属性进行某种键映射,并以某种方式将其映射到返回值,但我有点迷茫。

【问题讨论】:

    标签: typescript


    【解决方案1】:

    给你

    class Employee {
        constructor(data: any) {
            Object.assign(this, data);
        }
        position: string;
    }
    class Customer {
        constructor(data: any) {
            Object.assign(this, data);
        }
        clv: number;
    }
    
    type DeserializerTypes = { [n in string]: (data: {}) => {} };
    
    function createDeserializer<DS extends DeserializerTypes>(typeDeserializers: DS) {
        return <T extends keyof DS>(data: { __type: T }): ReturnType<DS[T]> => {
            const deserializer = typeDeserializers[data.__type];
            return deserializer(data) as ReturnType<DS[T]>;
        }
    }
    
    const personDeserializer = createDeserializer({
        'employee': (data) => new Employee(data),
        'customer': (data) => new Customer(data)
    });
    
    const person1 = personDeserializer({ __type: 'employee' }); // inferred as Employee
    const person2 = personDeserializer({ __type: 'customer' }); // inferred as Customer
    
    console.log(person1.position);
    console.log(1000 + person2.clv);
    

    但是如果你允许反序列化器参数中的属性,但仍然希望 TypeScript 推断出确切的类型,它会变得有点棘手:

    function createDeserializer<DS extends DeserializerTypes>(typeDeserializers: DS) {
        return <T extends keyof DS, D extends { __type: T }>(data: D): ReturnType<DS[D['__type']]> => {
            const deserializer = typeDeserializers[data.__type];
            return deserializer(data) as ReturnType<DS[T]>;
        }
    }
    
    const personDeserializer = createDeserializer({
        'employee': (data) => new Employee(data),
        'customer': (data) => new Customer(data)
    });
    
    const person1 = personDeserializer({ __type: 'employee', position: 'a' });
    const person2 = personDeserializer({ __type: 'customer', clv: 12 }); 
    
    console.log(person1.position);
    console.log(1000 + person2.clv);
    

    【讨论】:

    • 不错!非常感谢!
    猜你喜欢
    • 2014-01-06
    • 2012-09-09
    • 1970-01-01
    • 1970-01-01
    • 2020-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多