-
Notifications
You must be signed in to change notification settings - Fork 12.8k
[3.6 regression] Method unions with different generic defaults now error #32506
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
Comments
The prior behavior was to give |
Is it wrong to evaluate this as interface Instances {
Instance: Instance;
Model: Model;
Folder: Folder;
Camera: Camera;
ShakyCamera: ShakyCamera;
}
interface Instance {
ClassName: "Model" | "Folder" | "Camera" | "ShakyCamera";
Name: string;
Parent: Instance | undefined;
IsA<T extends this["ClassName"]>(className: T): this is Instances[T];
}
interface Model extends Instance {
PrimaryPart: Instance | undefined;
ClassName: "Model";
}
interface Folder extends Instance {
ClassName: "Folder";
}
interface Camera extends Instance {
ClassName: "Camera" | "ShakyCamera";
}
interface ShakyCamera extends Camera {
ClassName: "ShakyCamera";
}
function f(o: Folder | Model) {
if (o.IsA("Model")) {
// This expression is not callable.
// Each member of the union type
// '(<T extends "Model">(className: T) => this is Instances[T])
// | (<T extends "Folder">(className: T) => this is Instances[T]) '
// has signatures, but none of those signatures are compatible with each other.
o; // should be a Model
} else {
o; // should be a Folder
}
} In the above example, the type checker currently knows type GetProperties<T extends Instance> = {
[K in keyof T]: K extends "GetPropertyChangedSignal" | "ClassName" ? never : ((() => any) extends T[K] ? never : K)
}[keyof T];
interface Signal {}
interface Instance {
GetPropertyChangedSignal<T extends GetProperties<this>>(propertyName: T): Signal;
}
function g(o: Folder | Model) {
o.GetPropertyChangedSignal("Name");
// This expression is not callable.
// Each member of the union type
// '(<T extends "Name" | "Parent" | "PrimaryPart">(propertyName: T) => Signal)
// | (<T extends "Name" | "Parent">(propertyName: T) => Signal)'
// has signatures, but none of those signatures are compatible with each other.
} In this case, it should only allow |
Even in 3.6.0-dev.20190720, this is how the type checker acts if you move the type out of a generic parameter: interface Instance {
IsA<T extends keyof Instances>(className: T): this is Instances[T];
GetPropertyChangedSignal(propertyName: GetProperties<this>): Signal;
}
function h(o: Folder | Model) {
// Instance.GetPropertyChangedSignal(propertyName: "Name" | "Parent")
o.GetPropertyChangedSignal("Name");
if (o.IsA("Model")) {
// Instance.GetPropertyChangedSignal(propertyName: "PrimaryPart" | "Name" | "Parent")
o.GetPropertyChangedSignal("PrimaryPart");
}
} If you try a similar thing with the interface Instance {
IsA(className: this["ClassName"]): boolean;
}
function j(o: Folder | Model) {
o.IsA();
// IsA(className: never): boolean
} So, I guess the right answer here is intersection, which the type checker currently won't do for my first |
This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes. |
@RyanCavanaugh can we change this to an improvement request to make this work? I know type parameters like this our discouraged, but what the compiler is saying isn't true ("This expression is not callable"). In my case, I was using a "local type parameter" like this to relax the type checker's assignability checks. Shifting the type parameter's initializer to the return type causes many assignability errors (ex. I can't assign Edit: I ended up finding a workaround for this change, but it was sadly to code generate stuff in the user consumed declaration file (see diff for lib/ts-morph.d.ts). |
Also, I don't think this was added to the release notes as a breaking change? Edit: Actually, I guess looking at the other issues in the release there are lots of stuff that don't make the release notes. I'm not sure what's important enough to make it there, but was just wondering because it was mentioned that this should be in the release notes. |
TypeScript Version: 3.6.0-dev.20190720
Search Terms: Generic default conflict initializer
Code
Expected behavior: foo.bar() should return
1 | 2
in this caseActual behavior: error
The text was updated successfully, but these errors were encountered: