TypeScript: Cannot Optionalize Class Getters

TypeScript Version: 2.2.1

Code

class Person {
  firstName: string;
  lastName: string;

  get fullName?() {
    return this.firstName + ' ' + this.lastName;
  }
}

Expected behavior:

Since fullName is optional the following should work:

const Me: Person = {
  firstName: 'Foo',
  lastName: 'Bar'
}

Actual behavior:

A syntax error occurs on this line get fullName?() {

I’m not sure if omitting the ability to optionalize getters was by design or not. If it was by design, I’d love to know the reasoning behind it.

About this issue

  • Original URL
  • State: open
  • Created 7 years ago
  • Reactions: 48
  • Comments: 32 (6 by maintainers)

Most upvoted comments

@mhegazy Like bradenhs said, class methods can be made optional, as shown in this merged PR: https://github.com/Microsoft/TypeScript/pull/8625

class Bar {
    h?() {
        return 2;
    }
}

As can be seen, it’s an optional method that also has a body/implementation specified.

That’s the same thing we’d like for class getters/setters, like so:

class Bar {
    get h?() {
        return 2;
    }
}

However, this doesn’t compile currently, which seems inconsistent when class methods work with it fine.

@mhegazy seems inconsistent to allow (bodied) optional methods but not getters. Thoughts?

Seems this a real issue and still not implemented.

Thanks! I’m aware that that’s a possibility.

I suppose I just don’t understand why the language would disallow marking getters as optional when everything else on a class can be marked as optional. It seems inconsistent. Is there a good reason for this inconsistency? Forgive me if I misunderstand, but the “A class is an implementation of a type” reasoning seems more like a how-the-compiler-is-implemented reason as opposed to a how-the-language-should-work reason. I’m interested in the later.

A class is an implementation of a type. if you want to declare an optional property i suggest adding an interface Person:

interface Person {
   firstName: string;
   lastName: string;

  readonly fullName?;
}

Maybe I misunderstand. You can specify an implementation to an optional class method:

class Person {
  getName?() {
    return 'This is the name';
  }
}

There are no errors with that.

You don’t need this to solve your specific use case. You could just declare your class with constructor(other: {name: string}) or constructor(other: Partial<Entity>) or even constructor(other: Omit<Entity, "id">).

Finally had some time to go ahead and implement this. Take a look at the PR here #16344.

Oof. I just ran into this myself. Funny thing is the IDE (PhpStorm) doesn’t see get foo?() as a problem 😵

For now I did get foo(): string|null which compiles but doesn’t seem to be recognized by the IDE. Oh well.

Accepting PRs to allow this with similar semantics as optional methods.

any update? I am tired of writing entity.id(), i want entity.id but then creating the entity without id is not possible const entity = new Entity({name:'xyz}:Entity) // property id is missing

This should be allowed, which is only possible when id can be optional property.

I’m not sure @inad9300 's question is actually about #2521. set x(n: number | undefined) { } is valid and probably what they meant to specify. It’s not just that setters can’t have optional parameters, it’s that setters must always have exactly one parameter (and its type must be the same as the getter, if specified). They also can’t have two or ten parameters.

If you think about it for a second, though, it makes sense. The setter is called when an assignment operator is encountered, but a syntactically valid assignment always has exactly one l-value and one r-value, even if that r-value is undefined. Thus, you can’t ever call the setter function with anything other than exactly one argument, so it doesn’t make sense to support declaring it with anything other than exactly one parameter.