Skip to content
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

Design Meeting Notes, 10/02/2015 #5082

Closed
RyanCavanaugh opened this issue Oct 2, 2015 · 10 comments
Closed

Design Meeting Notes, 10/02/2015 #5082

RyanCavanaugh opened this issue Oct 2, 2015 · 10 comments
Labels
Design Notes Notes from our design meetings

Comments

@RyanCavanaugh
Copy link
Member

Linting

Linting is now turned on in the CI build 🎉

  • Can we make TSLint part of the build?
    • Yes. Make it part of ‘runtests’

Simple reachability checks

  • Done as part of the binder
  • Cheap in terms of perf
  • ~Couple hundred LOC
  • Found two bugs in the compiler
  • Has some checks for e.g. while(true), but nothing extra-fancy
  • Does not include definite assignment
    • Need a faster implementation of Set to do this quickly
    • Suggestion: use a dynamic-implementation Set using bit masks for sets with fewer than 32 members
  • How does a user opt in to this?
    • Good breaking changes: Code after 'return', for example, should be on by default
    • Controversial: No implicit return, no fall-through, etc.
    • What is our stance vs TSLint? e.g. ==, implicit ;, etc.
      • Type systems are kind of linty anyway
      • But we don't want to be in the business of style enforcement
      • What about plugins? Too complex. Maybe it can go in the Language Service, though?
  • Currently four options:
    • noUnusedLabels (on by default)
    • noFallThrough (off by default)
    • noImplicitReturn (off by default)
    • noUnreachableCode (on by default)
  • 'Strict' mode that combines some/all of these?
    • Nope
  • How do we name these? noImplicitAny vs allowImplicitAny, allowUnreachableCode vs noUnreachableCode
    • What about implicitAny=false?
    • What about these names makes them obviously boolean?
    • noFoo / allowFoo pairs?
    • Can we standardize on no ?
    • Commandline parser doesn't allow non-true boolean flags
    • Take offline and endure bikeshedding in the interim
  • 👍 in general

abstract enhancements

@RyanCavanaugh RyanCavanaugh added the Design Notes Notes from our design meetings label Oct 2, 2015
@denvned
Copy link
Contributor

denvned commented Oct 4, 2015

@RyanCavanaugh Regarding abstract properties, see my comment about why they are actually make sense. Workaround with delegating to protected methods requires more cluttered code, and have runtime performance overhead implications.

@mhegazy
Copy link
Contributor

mhegazy commented Oct 4, 2015

There is no distinction anywhere in the typeset stem between a getter/setter and a property declaration. So declaring an abstract setter for instance will not force the driver class to implement the property as a getter/setter pair.

@denvned
Copy link
Contributor

denvned commented Oct 5, 2015

@mhegazy Yes, I know that. That's why I'm actually proposing abstract property declarations, and not abstract getters/setters.

@denvned
Copy link
Contributor

denvned commented Oct 5, 2015

Today I can write:

interface A {
    p: number;
}
class B implements A {
    get p() { ... }
    set p(v: number) { ... }
}

But why should not I be able to write the following then?

abstract class A {
    abstract p: number;
}
class B extends A {
    get p() { ... }
    set p(v: number) { ... }
}

And forced to write the following instead:

abstract class A {
    get p() {
        return this.getP();
    }
    set p(v: number) {
        this.setP(v);
    }
    protected abstract getP(): number;
    protected abstract setP(v: number): void;
}
class B extends A {
    protected getP() { ... }
    protected setP(v: number) { ... }
}

@mhegazy
Copy link
Contributor

mhegazy commented Oct 5, 2015

The abstract here is irrelevant. in your example, adding an abstract modifier to a property declaration does not add any additional expressiveness, in the view of the type system, all these are equivalent:

abstract class A1 {
    p: number;
}

abstract class A2 {
    abstract p: number;
}


abstract class A3 {
    get p() { }
    set p(v) {}
}

abstract class A4 {
    abstract get p();
    abstract set p(v);
}

abstract class A5 {
    set p(v) {}
}

abstract class A6 {
    abstract get p();
}

all what the type system cares about is that there is a slot called 'p' on that type, and that it is a 'number'. getters/setters are not treated any differently from properties. moreover, there is no way to force a property to be implemented as getters/setter pairs. even missing a getter or a setter implementation does not affect that.

thus adding the abstract keyword will not add you any additional expressiveness, it will only save you from writing the body of a getter/setter functions but will not mean what you want it to mean. see #12 for more relevant discussion about setters/getters.

@denvned
Copy link
Contributor

denvned commented Oct 5, 2015

all what the type system cares about is that there is a slot called 'p' on that type, and that it is a 'number'. getters/setters are not treated any differently from properties. moreover, there is no way to force a property to be implemented as getters/setter pairs. even missing a getter or a setter implementation does not affect that.

As I already said, I know that. My point is that it should be possible to force a property to be not forgotten to be implemented by any means, not necessarily with getters/setters (but of course it will be usually implemented with getters/setters):

abstract class Prudent {
    abstract propertyYouMustNotForgetToImplement;
}
class Forgetful extends Prudent {
   // oops, I have forgotten something again
}

Here a compilation error should carefully remind us to implement the property. Without abstract it would be harder to achieve.

And when readonly will be here, we will be able to write abstract readonly someProperty;.

@mhegazy
Copy link
Contributor

mhegazy commented Oct 8, 2015

it should be possible to force a property to be not forgotten to be implemented by any means, not necessarily with getters/setters (but of course it will be usually implemented with getters/setters):

not sure i understand what you mean by "implemented". properties do not really exist in the emitted code. they are just a way for the type system to know the "shape" of your type. so whether you redclare them in the child class, or not, it has no functional impact.

I think what you are looking for is that the property is never null or undefined, i.e. initialized (either with a value, or a getter), as your base class have some dependency on its value, and this is tracked by #185

@denvned
Copy link
Contributor

denvned commented Oct 8, 2015

not sure i understand what you mean by "implemented"

We can implement a property by writing a custom getter/setter, or opt-out to the JavaScript default implementation, which is set/get a value associated with a key (property name) in a object.

properties do not really exist in the emitted code. they are just a way for the type system to know the "shape" of your type. so whether you redclare them in the child class, or not, it has no functional impact.

If you redeclare (implement) a property with a getter/setter then it actually exist in the emitted code, and obviously has a functional impact.

I think what you are looking for is that the property is never null or undefined

No, it is pretty much unrelated to what I am proposing.

Once more, abstract properties can make us sure that one of derived classes either implement a property with getter/setter, or consciously opt-out to the JavaScript "default implementation".

abstract class A {
    abstract p1;
    abstract p2;
    abstract p3;
    abstract p4;
}
class B extends A {
    get p1() { ... } // implement p1 with getter only

    set p2(v: number) { ... } // implement p2 with setter only

    // implement p3 with both getter and setter
    get p3() { ... }
    set p3(v: number) { ... }

    p4; // consciously opt-out to the JS default implementation for p4
}

Abstract properties can't enforce any of four alternatives above, but they can enforce that a property is consciously implemented in either way.

Abstract properties should work the same way properties declared in interfaces currently work.

@jbondc
Copy link
Contributor

jbondc commented Oct 10, 2015

Appreciate the notes, happy you guys are limiting the abstract box {}, ☀️ weather.

@craigbroadman
Copy link

As discussed here.... #4669

An abstract property is precisely what I need for using lambda/arrow functions (as they are actually properties)

"Class 'Base' defines instance member function 'def', but extended class 'Concrete' defines it as instance member property"...

abstract class Base {
    abstract abc(): void;
    abstract def(): void;
}

class Concrete extends Base {
    private setting: boolean;

    public abc(): void  {
        this.setting = true;
    }

    public def = (): void => {
        this.setting = false;
    }
}

@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Notes Notes from our design meetings
Projects
None yet
Development

No branches or pull requests

5 participants