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

this function argument type can not be narrowed to its subclass #35466

Closed
bogdan opened this issue Dec 3, 2019 · 4 comments
Closed

this function argument type can not be narrowed to its subclass #35466

bogdan opened this issue Dec 3, 2019 · 4 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@bogdan
Copy link

bogdan commented Dec 3, 2019

TypeScript Version: 3.5.3

Search Terms:

Code

type Attributes<T> = {[P in keyof T]? : T[P]};
class A {
  setAttributes(attributes: Attributes<this>) {
  }
}

class B extends A{
  async run(attributes: Attributes<B>) {
    this.setAttributes(attributes)
  }
}

Expected behavior:

No Error

Actual behavior:

tmp/test.ts:9:24 2345: Argument of type 'Attributes<B>' is not assignable to parameter of type 'Attributes<this>'.

I didn't find any way for this check to be relevant. If someone can point me out the use case where such check is required, please let me know.

Playground Link:

http://www.typescriptlang.org/play/?ssl=1&ssc=1&pln=24&pc=1#code/C4TwDgpgBAgswCcCWAjArsCBnAPAFQD4oBeKAbwG0AFKJAOygGsIQB7AMyjwF0B+KAFxdq3AL4BuAFABjADYBDLFljlJUKFgjA4iVBmwAKefGTpMWITtP7cwABZIsBAJSr1oyR5kKlUAEJQEAAemHQAJsowZGpQiiB00lAIaHRGJnrmlulm2Dh+Lm7qUPaOAHSa2tk2abo5WM4xHqJAA

@RyanCavanaugh
Copy link
Member

This is a correct error; in a derived class of B, there may be additional properties that would not be present in Attributes<B>

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Dec 9, 2019
@bogdan
Copy link
Author

bogdan commented Dec 10, 2019

Extra properties for derived class C from B are not getting accepted by C#run because it is the same as B#run which only accepts Attributes<B>, so it would not be possible to pass them into run. As all properties in Attributes<T> are optional, Attributes<B> will always be a subset of Attributes<this> in the base class.

See line 19:
http://www.typescriptlang.org/play/?ssl=15&ssc=1&pln=17&pc=1#code/C4TwDgpgBAgswCcCWAjArsCBnAPAFQD4oBeKAbwG0AFKJAOygGsIQB7AMyjwF0B+KAFxdq3AL4BuAFABjADYBDLFljlJUKPKFZE9AOYkoAckNT1WCMDg70mLAAp58ZDexCrzjNhzAAFkiwEAJSq6qKSYTIKSlAAQlAQAB6YdAAmyjBkalAoWjp0+qTGphpYIHTSUAhodA5OqJ5YbnUuuDFBIepQvv4AdOaWzQ211g2BWWERcorKAMLxSRCpynGZ6tK5yPkGReGSknQQAO5QM3aBPVU1ZJpG8oYANNlChigPUOtG0oaigUA

@RyanCavanaugh
Copy link
Member

Again, this is a correct error. Extra properties is just one form of subtyping that could occur here.

type Attributes<T> = {[P in keyof T]? : T[P]};
class A {
  a: string = '';
  setAttributes(attributes: Attributes<this>) {
  }
}

class B extends A{
  b: string = '';
  async run(attributes: Attributes<B>) {
    this.setAttributes(attributes)
  }
}

class C extends B {
  b: "foo" = "foo";

  setAttributes(attributes: Attributes<this>) {
    if (attributes.b !== undefined) {
      // Must be true, but is false
      console.log(attributes.b === "foo");
    }
  }
}

const b: B = new C();
b.run({ a: 'a', b: 'not foo' });

@bogdan
Copy link
Author

bogdan commented Dec 11, 2019

Wow! I see what you mean now, thanks for explanation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

2 participants