-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug Report + Proposal: Object.assign() #31982
Comments
Relevant comment (in #28553) saying why this is not already being done:
Relevant possible implementation (in #21316) of a class A {
c?: boolean;
constructor(public a: string) {}
sayA() {
console.log(this.a);
}
}
class B extends A {
constructor(a: string, public b: string) {
super(a);
}
}
function hmm(a: A) {
return assign({ b: 123, c: 456 }, a);
}
const result = hmm(new B("a", "b"));
// unknown properties
result.b; // number at compile time, but:
console.log(typeof result.b); // "string"
// optional properties
result.c; // boolean | undefined at compile time, but:
console.log(typeof result.c); // "number"
// non-own properties
result.sayA; // function at compile time, but:
console.log(typeof result.sayA); // "undefined" |
Thanks, @jcalz, and great example!
It's bit of a shame as there's been a heap of improvements in soundness recently, really loving the direction! Not that I think it's particularly compelling on its lonesome, but just for reference, I am seeing overlapping types being assigned. Specifically custom "sub-classes", default props of Anyway, I do totally understand the decision though. I guess it'd only be feasible with first class support for "exact types" (#12936), and my head is hurting just thinking about how much that'd further complicate the types here. I also noted that when chained my let x: number
Object.assign({}, "abcde", [1, 2, 3])[x] // string | number Hopefully this will become a bit more feasible in near future; I'm a sucker for soundness. |
For future reference, whilst without a doubt it's far superior to my own attempt, @ahejlsberg's implementation unfortunately does have a couple of failures when run against my test suite. Failing EDIT: It's quite conceivable that I can't just naively apply the |
You've got type OptionalPropertyNames<T> = { [K in keyof T]-?:
({} extends { [P in K]: T[K] } ? K : never)
}[keyof T] which should fix that particular issue, but I feel unclean even thinking about what happens when |
Ugh, spot on, thank you! 😊 ... and that's my call to go to bed (don't look at my time zone 😉).
Looks like I'm too far gone. 😉 However, in all seriousness, @ahejlsberg's implementation is fantastic and ticks all the boxes, my sincerest apologies for falsely calling out failing tests! I'm not sure whether this issue should remain open to track the state of |
There's an additional trade-off here because it's desirable for So anyway for concrete types, |
That seems like a very peculiar thing to infer. I can understand why people may be expecting EDIT: In the paragraph above "partials" was a very poor choice of word, as e.g. A React component might spread/assign its props ( Given that TypeScript wants to facilitate writing correct & maintainable software, I would ideally like to see changes that cause developers to disperse with these sorts of false assumptions. However, I totally understand what's proposed is a rather large change; and I'm certainly not expecting anyone to rashly make decisions. Nonetheless, I'm a bit sad to see this labelled as 'Working as intended' given the design goals of the language. Anyway, I'll just keep my fingers crossed there'll be a change of heart at some point 🤞 |
Maybe "Best Available Compromise" is the better label |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
TypeScript Version: 3.4.0-dev.201xxxxx
Search Terms: Object.assign return type
Code
Expected behavior:
Actual behavior:
No errors raised.
Playground Link: Link
Related Issues:
Proposal
Note 1:
PickDefined<T>
is necessary withstrictNullChecks
enabled.Note 2: In the definition of
Assign<A, B>
I would have expected the usage ofkeyof B
to need to be replaced withkeyof PickDefined<B>
. It seems, that's presently not the case - so I've opted to omit it and avoid any potential slow-down. Nonetheless, I must admit that I'm hazy as to why this is permissible.Obviously to keep things brief I've just covered the single
source
use-case rather than providing overloads with several source. The definition is nonetheless chainable i.e.Assign<A, Assign<B, C>>
etc.Playground Link: Link (For posterity please enable
strictNullChecks
)The text was updated successfully, but these errors were encountered: