-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Defining a type predicate breaks inheritance for methods with mapped types #56133
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
It's not the type predicate but rather the reference to Note that your const item: Arbitrary<string> = {} as MyArbitrary<number> We can see a somewhat better error here as it at least refers to the method that references |
This seems like a bug: // No constraint: OK
{
interface Arbitrary<T> {
cov: T;
xyzzy<U>(x: { [K in keyof U]: U[K] }): Arbitrary<U>;
}
class MyArbitrary<T> implements Arbitrary<T> {
cov!: T;
xyzzy<U>(x: { [K in keyof U]: U[K] }): Arbitrary<U> {
return null as any;
}
}
}
// Use a type alias: OK
{
type SomeMap<U> = { [K in keyof U]: U[K] };
interface Arbitrary<T> {
cov: T;
xyzzy<U extends unknown[]>(x: SomeMap<U>): Arbitrary<U>;
}
class MyArbitrary<T> implements Arbitrary<T> {
cov!: T;
xyzzy<U extends unknown[]>(x: SomeMap<U>): Arbitrary<U> {
return null as any;
}
}
}
// Neither: Error
{
interface Arbitrary<T> {
cov: T;
xyzzy<U extends unknown[]>(x: { [K in keyof U]: U[K] }): Arbitrary<U>;
}
class MyArbitrary<T> implements Arbitrary<T> {
cov!: T;
xyzzy<U extends unknown[]>(x: { [K in keyof U]: U[K] }): Arbitrary<U> {
return null as any;
}
}
} |
BTW, I noticed last night the weirdness that is function record<T>(recordModel: { [K in keyof T]: Arbitrary<T[K]> }):
Arbitrary<RecordValue<{ [K in keyof T]: T[K] }>>; I think the variable |
I don't know if this is the case here but type ID<T> = { [K in keyof T]: T[K] }; is a common pattern people sometimes write to get TS to fully expand object types in hover tips. AFAIR it's just a no-op on primitive types so it's nice to be able to use it in situations where an |
I'm looking into this, so far I think the discrepancy in #56133 (comment) is due to inference, which we perform when we compare two signatures that have type parameters (in this case the signatures for |
Ok, as I mentioned above, the reason why the code errors is, I think, because of inference. What happens when type checking the code is roughly the following:
All the variants in this comment that make the error go away do so by changing how we infer the type arguments for the source signature during |
Let's try to use a cleaner example for all discussions here: declare class Base<T> {
someProp: T;
method<U extends unknown[]>(x: { [K in keyof U]: U[K] }): Base<U>;
}
declare class Derived<T> extends Base<T> {
method<U extends unknown[]>(x: { [K in keyof U]: U[K] }): Base<U>;
} |
Let's use unique type parameter names when discussing issues related to unification: declare class Base<T> {
someProp: T;
method<U extends unknown[]>(x: { [K in keyof U]: U[K] }): Base<U>;
}
declare class Derived<S> extends Base<S> {
method<V extends unknown[]>(x: { [K in keyof V]: V[K] }): Base<V>;
} Makes it clearer that |
π Search Terms
type predicate mapped
π Version & Regression Information
β― Playground Link
https://www.typescriptlang.org/play?ts=5.2.2#code/IYIwzgLgTsDGEAJYBthjAgglEBLawUAngDwAqAfAgN4BQCCokM8SwAdgMoAWUu7AawDq+bgHsArhADCY9hACmADwgAKAG7BkEhQC4EEwezEB3dgEp9m7QoS4MZANy16jcAVZKiAL2+kAqhjKiuwAJhiGAsZmANoAuhSqrgxK+tQIMQDSduwIAgpEYgBmCIFx+oFZcQgAvgA0rpZYOPgwxCSBFM41LkweiChoGACyRNh4BO2UCMEKYRjjrYSk03QMfSyIXr4BQSpz4QZGpuzxickIqTQZ2fx5BcWlYOVPVbUNDE2Lk7tdtD1AA
π» Code
π Actual behavior
The compiler reports an error in
MyArbitrary
unlesscanShrinkWithoutContext
is removed or its return type is changed.π Expected behavior
The
xyzzy
method should be overridden in the derived class.Additional information about the issue
No response
The text was updated successfully, but these errors were encountered: