We're looking for a type safe way of using Object.assign. However, we can't seem to make it work.
To show our problem I'll use the copyFields method from the Generics documentation
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"
}
I want the engine to prevent me from creating undeclared properties
/*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
We have attempted to solve this with explicitly providing the types to the copyfields call but we can't find a call that will make all examples work.
For example: to make 5 work you might call copyFields like this:
/*5'*/copyFields<Source,{a?:"a"|"b"}>(makesrc(), {a: "b"});
but subsequent changes to the Source type (such as removing the "b" option) will now no longer result in a type error
Does anyone know of a way to make this work?
You can use Object.assign<TargetType, SourceType>(target, source)
- I think it provides type safety.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With