安全输入Object.assign

ren*_*ark 5 typescript

我们正在寻找一种使用Object.assign的类型安全的方法.但是,我们似乎无法使其发挥作用.

为了显示我们的问题,我将使用Generics文档中的copyFields方法

function copyFields<T extends U, U>(target: T, source: U): T {
    for (let id in source) {
        target[id] = source[id];
    }
    return target;
}

function makesrc(): Source { return {b: 1, c: "a"}}

interface Source {
    a?: "a"|"b",
    b: number,
    c: "a" | "b"
}
Run Code Online (Sandbox Code Playgroud)

我希望引擎阻止我创建未声明的属性

/*1*/copyFields(makesrc(), {d: "d"}); //gives an error
/*2*/copyFields(makesrc(), {a: "d"}); //gives an error
/*3*/copyFields(makesrc(), {c: "d"}); //should give an error, but doesn't because "a"|"b" is a valid subtype of string.

//I don't want to specify all the source properties 
/*4*/copyFields(makesrc(), {b: 2}); //will not give me an error
/*5*/copyFields(makesrc(), {a: "b"}); //should not give an error, but does because string? is not a valid subtype of string 
Run Code Online (Sandbox Code Playgroud)

我们试图通过明确地向copyfields调用提供类型来解决这个问题,但我们找不到一个能让所有例子都起作用的调用.

例如:为了使5工作你可以像这样调用copyFields:

/*5'*/copyFields<Source,{a?:"a"|"b"}>(makesrc(), {a: "b"}); 
Run Code Online (Sandbox Code Playgroud)

但是对Source类型的后续更改(例如删除"b"选项)现在将不再导致类型错误

有谁知道如何使这项工作?

Jau*_*uco 1

Typescript 2.1.4 来救援!

游乐场链接

interface Data {
    a?: "a"|"b",
    b: number,
    c: "a" | "b"
}

function copyFields<T>(target: T, source: Readonly<Partial<T>>): T {
    for (let id in source) {
        target[id] = source[id];
    }
    return target;
}

function makesrc(): Data { return {b: 1, c: "a"}}

/*1*/copyFields(makesrc(), {d: "d"}); //gives an error
/*2*/copyFields(makesrc(), {a: "d"}); //gives an error
/*3*/copyFields(makesrc(), {c: "d"}); //gives an error

//I don't want to specify all the source properties 
/*4*/copyFields(makesrc(), {b: 2}); //will not give me an error
/*5*/copyFields(makesrc(), {a: "b"}); //will not give me an error
Run Code Online (Sandbox Code Playgroud)