-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
please delete, thx #60524
Comments
setting
|
Note: not a TS team member. Duplicate of #11100, tracked at #10727.
And even if that existed it would still fail to catch problems in general without exact types as per #12936, since nothing prevents you from sneaking random extra stuff in there: const x = { template: 123 }
const y: {} = x; // okay
const base: Thing = { template: "foobar" }; // Thing
const result = Object.assign({}, base, y); // Thing?!
result.template.toUpperCase(); // runtime explosion because it's really a number So |
yep, that seems to help, sadly in my case the property will be set by the user of the library I'm trying to build (hence the name EDIT: I have now tested this further and enabling the setting does not change the behaviour of @jcalz the major issue I see with your example is the use of |
"acts virtually identical to interface Thing {
template: string;
color?: string;
}
const x = { color: "abc", template: 123 }
const y: { color: string } = x;
const base: Thing = { template: "foobar" }; // Thing
const result = Object.assign({}, base, y); // Thing & {color: string}
result.template.toUpperCase(); // runtime explosion because it's really a number Does that demonstrate the issue to you? |
This does not disprove
This exits the realm of explicilty setting |
I was hoping to avoid this discussion by changing the example. I agree that
Widening is not "lying" to TypeScript's type analysis. The following is not lying, it's just widening: interface Foo { x: string }
interface Baz extends Foo { y: string }
function f(foo: Foo): Baz { return Object.assign({}, { y: "abc" }, foo); }
interface Bar extends Foo { y: number }
const bar: Bar = { x: "abc", y: 123 };
const baz = f(bar);
baz.y.toUpperCase() // error If you want to fix that problem, you need exact types. If you think it's off-topic, let's forget about it entirely. Sorry for the digression. Optional properties accept type Arg = { [K in keyof Thing]: Thing[K] | undefined };
/* type Arg = {
template: string | undefined;
color?: string | undefined;
} */
const base: Thing = { template: "foobar" }; // Thing
const arg: Arg = { color: "red", template: undefined }; // Arg
const result = Object.assign({}, base, arg); // Thing & Arg
result.template // string Indeed we can change type Arg = { [K in keyof Thing]: Thing[K] | number };
/* type Arg = {
template: string | number;
color?: string | number;
} */
const base: Thing = { template: "foobar" }; // Thing
const arg: Arg = { color: "red", template: 123 }; // Arg
const result = Object.assign({}, base, arg); // Thing & Arg
result.template // string The problem here is the lack of a spread operator. Here's a possible spread implementation: type MergeTwo<T extends object, U extends object> = { [
K in keyof T | keyof U]:
(x: K extends (keyof T & keyof U) ?
{} extends Pick<U, K> ? { [P in keyof T as P & K]: T[P] | U[K] } : Pick<U, K> :
K extends keyof T ? Pick<T, K> : K extends keyof U ? Pick<U, K> : never) => void
} extends Record<keyof T | keyof U, (x: infer I) => void> ? { [K in keyof I]: I[K] } : never
type Merge<T extends object[], A extends object = object> =
T extends [infer F extends object, ...infer R extends object[]]
? Merge<R, object extends A ? F : MergeTwo<A, F>> : A;
interface ObjectConstructor {
assign<T extends [object, ...object[]]>(...args: T): Merge<T>
} which gives you type Arg = Partial<Thing>;
const base: Thing = { template: "foobar" }; // Thing
const arg: Arg = { color: "red", template: undefined }; // Partial<Thing>
const result = Object.assign({}, base, arg);
/* const result: {
template: string | undefined;
color?: string | undefined;
} */
result.template // string | undefined
const y = Object.assign({}, base, { template: Math.random() < 0.99 ? 123 : "abc" })
/* const y: {
template: string | number;
color?: string | undefined;
} */ But that |
can you cease writing essays about unrelated stuff in my issue please? |
It’s not unrelated. As for writing essays, that’s a fair point. I’ll disengage now entirely. Good luck. |
Your write-up is still appreciated for future reference. |
This comment has been minimized.
This comment has been minimized.
@MartinJohns Please immediatly remove the above screenshot. My personal social media are not yours to share, this ticket is closed and I have already requested deletion. |
😭 I don't know quite what's going on here, but I'm sorry for my part in it. I'm going to unsubscribe from this. If you need my attention please @-mention me. Good luck. |
Dunno why I thought using github issues in public was a valid way to report incorrect behaviour in software.
The text was updated successfully, but these errors were encountered: