用于将[keys] .option.value.number转换为选项的通用接口。[Keys] .number

时间:2018-01-20 19:24:01

标签: typescript generics interface

我正在尝试使用通用打字和打字稿界面来描述以下情况。 当函数将工厂创建的对象的属性从[keys] .option.value。(number | string ...)转换为选项。[Keys]。(number | string ...)

在最后一行我使用intValue而不是数字。对于Values类型有什么魔力吗?

Code on typescript playground

interface Validator { }

interface Value<T> { 
    value: T
    validator: Validator
}

interface intValue extends Value<number> {}
interface stringValue extends Value<string> {}

interface Entity {
    (key: string): intValue | stringValue
}

interface Dog extends Entity {
    id: intValue;
    age: intValue;
    name: stringValue;
} 

function initObject<E extends Entity>(arg: E): E {
    return arg;
}

function initInt(value: number, validator: Validator): intValue {
    return {
        value: value,
        validator: validator
    }
}

function initString(value: string, validator: Validator): stringValue {
    return {
        value: value,
        validator: validator
    }
}

type Values<T> = {
    [P in keyof T]?: T[P];
}

interface Valued<V> {
    values: Values<V>;
    validators: Values<V>;
}

function getValued<V extends Entity>(obj: V): Valued<V>{
    let out: Valued < V > = {values:[]};

    for (let key in obj) {
        const o:intValue = obj[key];
        out.values[key] = o.value;
        out.validators[key] = o.validator;
    }

    return out;
}

const objectDog = initObject(<Dog>{
    id: initInt(1, {}),
    age: initInt(12, {}),
    name: initString("Nuf", {})
})

const valuedDog = getValued(objectDog);
valuedDog.values.id; // There id is type intValue i want get number type here

谢谢,求助。

2 个答案:

答案 0 :(得分:1)

我无法花时间浏览所有代码,但看起来就像您希望str1[3] * hex_np + str2[5]的定义如下:

Values<>

也就是说,type Values<V extends Entity> = { [P in keyof V]?: V[P]['value']; } 类型应该“展开”Values<V>中的属性值。然后,您只需将V更改为Valued<V>

Valued<V extends Entity>

然后你的代码类型检查并返回或多或少的你想要的东西(好吧,它是interface Valued<V extends Entity> { values: Values<V>; validators: Values<V>; } ,因为number | undefined属性是可选的...如果你删除Values<>不要那样)。不确定代码是否符合您的要求,但您可能是最好的判断。

希望有所帮助;祝你好运!

答案 1 :(得分:0)

我按照您的描述获得了以下代码。我认为这些变化是可以接受的。如果没有,请说明原因,我会再看看。

interface Validator { }

interface Value<T> { 
    value: T
    validator: Validator
}

interface intValue extends Value<number> {}
interface stringValue extends Value<string> {}

interface Entity {
    (key: string): intValue | stringValue
}

interface Dog extends Entity {
    id: intValue;
    age: intValue;
    name: stringValue;
} 

function initObject<E extends Entity>(arg: E): E {
    return arg;
}

function initInt(value: number, validator: Validator): intValue {
    return {
        value: value,
        validator: validator
    }
}

function initString(value: string, validator: Validator): stringValue {
    return {
        value: value,
        validator: validator
    }
}

type Values<T> = {
    [P in keyof T]?: T[P];
}

interface Valued<V> {
    values: Values<V>;
    validators: Values<V>;
}

function getValued<V extends Entity>(obj: V): Valued<V>{
    // initialize to empty object not array and initialize validators
    let out: Valued<V> = { values: {}, validators: {} }; 

    // const instead of let
    for (const key in obj) {
        const o:intValue = obj[key];
        out.values[key] = o.value;
        out.validators[key] = o.validator;
    }

    return out;
}

const objectDog = initObject(<Dog>{
    id: initInt(1, {}),
    age: initInt(12, {}),
    name: initString("Nuf", {})
}); // semicolon

const valuedDog = getValued(objectDog);

// Added .value here
valuedDog.values.id.value;

P.S。我希望这种抽象风格有一个真正的充分理由。