首页 > 解决方案 > 如何将一个泛型的结构复制到另一个泛型,用自定义值替换原始值?

问题描述

首先阅读这个问题可能会有所帮助:如何在 TypeScript 中将一个泛型类型的结构复制到另一个泛型?

给定以下输入类型:

interface InputType {
    age: number;
    surname: string;
}

我想要一个可以为上述输入生成以下输出类型的函数:

type OutputValue<T> = (val: T) => void;

interface OutputType {
    age: OutputValue<number>;
    surname: OutputValue<string>;
}

这个函数的签名是:

type OutputType<T> = {
    [k in keyof T]: OutputValue<T[k]>
}

type TransformationFunction<Input, Output extends OutputType<Input>> = (input: Input) => Output;

上面的类型签名将确保输出是类型安全的。这意味着我可以使用智能感知来正确检索output.surname函数(例如)。

棘手的部分是以类型安全的方式返回正确的数据结构。

这是我的尝试:

const transformString = (stringValue: string) => {
    return (val: string) => {
        // some code processing val
    }
}

const transformationFunction = function<Input, Output extends GenericMap<Input>>(input: Input): Output {
    const keys = Object.keys(input) as Array<keyof Input>;

    return keys.reduce((output: Output, key: keyof Input) => {
        const inputValue = input[key];

        if (/*typeguard*/ isString(inputValue)) {
            return transformString(inputValue); // typescript compiler complains
        }
        else if ( /*typeguard*/ isNumber(inputValue)) {
            return transformNumber(inputValue); // similar function to above + typescript complains
        }
        else {
            throw new Error("No transform");
        }
    }, {} as Output)
}

如何将自定义值应用于输出对象?

实际问题的游乐场

标签: javascripttypescripttypescript-generics

解决方案


使用 for 循环而不是 reduce,这成为可能:

(output[key] as unknown as OutputValue<string>) = transformString(inputValue)

而不是return transformString(inputValue)期望OutputValue<Input[keyof Input]>

游乐场链接


推荐阅读