-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
feat(14417): add optionality to accessors #45662
Conversation
d2f306f
to
298ea35
Compare
The TypeScript team hasn't accepted the linked issue #14417. If you can get it accepted, this PR will have a better chance of being reviewed. |
I think the addition of I would expect that accessors cannot be optional, and that they should only explicitly specify |
I have yet to read more and understand the whole set vs define semantics, but is that only applicable to properties that are not methods? |
@DanielRosenwasser Thanks for the feedback. 👍🏻
TypeScript allows optional methods ( class Foo {
a?() {}
b?: number;
get c?() { ... } // Error
} If it doesn't make sense to allow using |
Thinking on it some more, I think it makes sense structurally. You can have an object that omits these properties and is compatible with the instance type. You may want to add a test for optional accessors that return export class C {
get foo?(): number { return 42; }
set foo?(value: number) {}
}
declare let x: {
foo: number | undefined;
}
let y: C = x; Other thoughts:
Yeah, my concern here had to do with whether the property was placed on the instance vs. the prototype. This doesn't have much to do with if a property was created with |
298ea35
to
46b7f35
Compare
I discussed the original issue with @sandersn and here's our concerns:
interface I {
set m?(value: string): void;
}
declare var i: I;
i.m = "oops"; // This is going to throw if `set m()` is not defined on `i` compared to when we know, statically, that the setter is not defined: interface I {
get m(): string;
// no setter!
}
declare var i: I;
i.m = "oops"; // Compiler error: `m` is treated as a `readonly` property, because we have a getter but not a setter. The way to check if a setter is present is like this: interface I {
set m?(value: string): void;
}
declare var i: I;
if (typeof Object.getOwnPropertyDescriptor(i, 'm')['set'] === 'function') {
... // we could narrow the type of `i.m` here, but it seems rather convoluted
}
interface I {
get m?(): string;
}
declare var i: I;
i.m; // `undefined` if `get m()` is not defined. but I can't tell how much having that would make sense, considering the benefits vs. the costs in terms of maintenance and confusing users. I think we might be better off without this feature, because even though at a first glance it might seem like accessors can be treated just like properties, there are some underlying subtleties that makes it more complicated. |
46b7f35
to
5b0bdc7
Compare
5b0bdc7
to
ca0e616
Compare
@DanielRosenwasser @sandersn @rbuckton given the concerns I wrote in the comment above, should we close this PR and its issue? |
I wholeheartedly agree, and am happy to classify this PR as "not accepted". The issue can probably remain as a discussion (and I've relabeled it as such); maybe someone can design something with a set of rules that's not terrible to use, however doubtful that seems given current class field behavior. |
Fixes #14417