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

Structural typing undermining type safety #5933

Closed
alexpomsft opened this issue Dec 4, 2015 · 4 comments
Closed

Structural typing undermining type safety #5933

alexpomsft opened this issue Dec 4, 2015 · 4 comments
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript

Comments

@alexpomsft
Copy link

class Dog {furColor: string}
class Cat {}

function walk(d: Dog): void {}
function pet(c: Cat): void {}

const d: Dog = {furColor: "brown"};
const c: Cat = {};

walk(c); // error, good!
pet(d); // no error, bad!

Ryan and I have had extensive conversations about this problem. In my opinion this should clearly fail since both Dog and Cat are classes. Type safety should ensure that when we demand a class type the thing passed in should be in the inheritance chain. Structural typing shouldn't apply to classes.

There's an argument to be made that this case also shouldn't be supported for interfaces, which I'm also sympathetic to. This similar example proves the problem:

interface Dog {furColor: string}
interface Cat {}

function walk(d: Dog): void {}
function pet(c: Cat): void {}

const d: Dog = {furColor: "brown"};
const c: Cat = {};

walk(c); // error, good!
pet(d); // no error, bad!

However, if we mark furColor as optional, I think there's a totally valid argument to be made that it should compile and the desired behavior is met, e.g.

interface Dog {furColor?: string}
interface Cat {}

function walk(d: Dog): void {}
function pet(c: Cat): void {}

const d: Dog = {furColor: "brown"};
const c: Cat = {};

walk(c); // no error, good!
pet(d); // no error, good!
@zpdDG4gta8XKpMCd
Copy link

so what is the take out of what you said? what's the action item?

@Arnavion
Copy link
Contributor

Arnavion commented Dec 6, 2015

A similar thing is the ability to assign object literals to class types as long as they have the same members, but currently constructor is not such a required member. So this issue is a prerequisite for #3841

class Foo {
    constructor(public prop: string) { }
    static bar() { }
}

var foo = new Foo("5");
foo.constructor.bar(); // Currently not allowed. Would be allowed if #3841 is implemented.

var foo2: Foo = { prop: "5" }; // Currently allowed
foo2.constructor.bar(); // Currently not allowed. Should continue to not be allowed if #3841 is implemented, which means the assignment itself should be disallowed.

@mhegazy mhegazy added Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript labels Dec 8, 2015
@mhegazy
Copy link
Contributor

mhegazy commented Dec 8, 2015

This is an issue that we have talked about on and off over the past years. for this to proceed we will need a proposal for how this fits in the current system, what are the proposed new rules for comparing class types, what impact of a change does this have on existing code (we can help out with part by running the ts internal snapshot of real world code bases).

@RyanCavanaugh
Copy link
Member

I think some day we might revisit class nominality, but we haven't seen any proposals we really like yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs Proposal This issue needs a plan that clarifies the finer details of how it could be implemented. Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

5 participants