如何从TypeScript中的泛型部分构建目标对象? [英] How to build up a target object from generic partials in TypeScript?

查看:79
本文介绍了如何从TypeScript中的泛型部分构建目标对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用typescript@2.3.4.

I am using typescript@2.3.4.

我有一个目标对象:

interface MyTarget {
    a: string;
    b: string;
    c: string;
    d: string;
}

我想使用泛型创建多个部分对象转换.

I want to create multiple converts of partial objects using generics.

一个这样的转换可能看起来像这样:

One such convert might look like this:

const convert = <T extends object>(t: T): MyTarget => {
    return {
        c: "c",
        d: "d",
        ...t,
    };
};

但是这产生了:

error TS2698: Spread types may only be created from object types.

即使我保护通用的 T 成为 object .

even though I guard the generic T to be an object.

然后我记得有一个 Partial 类型,因此我尝试了此操作:

I then remember that there is a Partial type, hence I tried this:

const convert = (partial: Partial<MyTarget>): MyTarget => {
    return {
        c: "c",
        d: "d",
        ...partial,
    };
};

但是 Partial 使所有属性都是可选的.我不想要它,现在它会抛出:

Yet the Partial makes all properties optional. I don't want that and it would now throw:

src/Partial.ts(14,5): error TS2322: Type '{ a?: string; b?: string; c: string; d: string; }' is not assignable to type 'MyTarget'.
  Property 'a' is optional in type '{ a?: string; b?: string; c: string; d: string; }' but required in type 'MyTarget'.

我想创建一个 MyTarget 的实例,并将每个字段设置为要求.我确实想保留类型安全性,这就是即使有效的我也不想这样做的原因:

I want to create an instance of MyTarget with every field set as an requirement. I do want to keep typesafety, which is why I don't want to this even though it works:

const convert = (partial: Partial<MyTarget>): MyTarget => {
    return {
        c: "c",
        d: "d",
        ...partial,
    } as MyTarget; // loses type checks, really don't want to
};

推荐答案

我认为您使用的是TS的较旧版本(在较新的版本中,正确键入了扩展表达式).

I think you are using an older version of TS (in newer version spread expressions are typed correctly).

无论如何,真正的问题是对象文字可能不是完整的 MyTarget .您的代码将允许此调用

Regardless of this, the true issue is that the object literal might not be a full MyTarget. Your code would allow this call

convert({a : "" })// return value is not really MyTarget since it will not contain b

您真正想要的是除 c d 之外的参数 MyTarget :

What you really want is the parameter to be MyTarget except c and d:

interface MyTarget {
    a: string;
    b: string;
    c: string;
    d: string;
}
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
const convert = (t: Omit<MyTarget, 'c' | 'd'>) : MyTarget => {
    return {
        c: "c",
        d: "d",
        ...t,
    };
};

这篇关于如何从TypeScript中的泛型部分构建目标对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆