-
Notifications
You must be signed in to change notification settings - Fork 12.8k
"Two different types with this name exist, but they are unrelated" emitted when same #26627
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
related to #25373 ? |
I think this is a different issue having to do with conditoinal types. interface I {
m<T>(): T extends Array<infer U> ? U : never
}
class C implements I {
m<T>(): T extends Array<infer U> ? U : never { // Error?
throw new Error();
}
} Also, the following should be an error but isn't: interface I {
m<T>(): T extends Array<infer U> ? U : never
}
class C implements I {
m<T>(): T {
throw new Error();
}
} |
The issue here is that conditional types with inference positions (i.e. The simple workaround is to declare a type alias and use this type alias in both places: type CtorParams<T> = C extends Constructor<infer T> ? T : never;
interface X {
decode<C extends Constructor<any>>(ctor: C): MappedResult<CtorParams<T>>
}
class Y implements X {
decode<C extends Constructor<any>>(ctor: C): MappedResult<CtorParams<T>> {
throw new Error()
}
} This causes the checker to realize the types are the same. |
@Andy-MS The second issue isn't really meaningful because Consider this instead: interface A {
m<T>(x: T[]): T[];
}
interface B extends A {
m<U>(x: U): U;
} The above example is fine because when we instantiate interface A {
m<T>(x: T): T[];
}
interface B extends A {
m<U>(x: U): U;
} This error is caused by inferring both |
The same sort of issue still exists from #16786. Consider the following (this works in C# if you look at the Enumerable.cs class: https://github.com/Microsoft/referencesource/blob/4.6.2/System.Core/System/Linq/Enumerable.cs) export interface IOrderedEnumerable<T> extends IEnumerable<T> {
thenBy<TKey>(selector: (in1: T) => TKey, comparer?: IComparer<TKey>): IOrderedEnumerable<T>;
thenByDescending<TKey>(selector: (in1: T) => TKey, comparer?: IComparer<TKey>): IOrderedEnumerable<T>;
}
export class OrderedEnumerable<T, TKey> extends Enumerable<T> implements IOrderedEnumerable<T> {
// other code here omitted
thenBy(selector: (in1: T) => TKey, comparer?: IComparer<TKey>): IOrderedEnumerable<T> {
throw new Error("Not implemented");
}
thenByDescending(selector: (in1: T) => TKey, comparer?: IComparer<TKey>): IOrderedEnumerable<T> {
throw new Error("Not implemented");
}
} As you see in the concrete class above, the TKey generic should be inferred from the class for those thenBy functions, but the compiler fails with the "Two different types with this name exist, but they are unrelated" error. |
@ahejlsberg Your workaround works great, thanks! This is pretty confusing when you run into it the first time. The documentation on conditional and inferred types should mention something about this. |
…the target conditional (microsoft#31545) * Instantiate generic conditional infer source types in the context of the target conditional * Add test case from microsoft#26627
@ahejlsberg this work around works! Finally found it after wasting hours searching for the solution. This is especially annoying when trying to wrap a type as a promise, since that also doesn't work correctly with specifying a separate promise-wrapped type. Any new on if this is going to be fixed? |
TypeScript Version: Version 3.1.0-dev.20180823
Search Terms: Different types with same name
Code
Expected behavior: It should compile without any error. Everything is in the same namespace, so it should be the same type.
Actual behavior: The quoted error below is emitted.
Playground Link: Here
Related Issues: None I can find
The text was updated successfully, but these errors were encountered: