Pick<T, Exclude<keyof T, K>> & Pick<T, Extract<keyof T, K>> should be assignable to T
See original GitHub issueTypeScript Version: 3.2.1
Search Terms: 3.2.1 extends intersection generic
Code
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
type Func<T> = (arg: T) => null
type Context = 'Context';
export function withRouteContextPropConsumer<
T extends { routeContext: Context }
>(
funcToWrap: Func<T>,
): Func<Omit<T, "routeContext">> {
return (args: Omit<T, "routeContext">) => {
const routeContext: Context = 'Context';
return funcToWrap({ ...args, routeContext });
};
}
Expected behavior: Code compiles without errors
Actual behavior:
Argument of type '{ routeContext: "Context"; }' is not assignable to parameter of type 'T'.
After upgrading from 3.0.3 to 3.2.1, it seems that tsc has (at least partially) lost the ability to reason about constrained generics.
In the example above (one of our React context helper functions, modified to remove the React dependency), the function is parameterised over a constrained generic:
T extends { routeContext: Context }
But a few lines later, the compiler complains that the generic T
may not have a routeContext
attribute. T must have a routeContext
attribute however, because of the constraint. Perhaps the Omit
helper is confusing things?
Issue Analytics
- State:
- Created 5 years ago
- Reactions:18
- Comments:17 (4 by maintainers)
Top Results From Across the Web
Type '1' is not assignable to type 'T[Extract<keyof T, string>]'
I thought T[Extract<keyof T, string>] is number so assigning 1 which is number should work. What is wrong in my code? type Foo...
Read more >How to use the keyof operator in TypeScript - LogRocket Blog
keyof T returns a union of string literal types. · extends means “is assignable” instead of “inherits”; K extends keyof T means that...
Read more >Enforce that all keys in a map are a key of a certain type ...
type KeyOf<T> = Extract<keyof T, string>. And our function will now look like so: function foo<T>(someKey: KeyOf<T>) { const myMap = new Map()...
Read more >Error - Type 'string[]' is not assignable to type 'keyof MyInterface[]'
keyOne: string keyTwo: string } const myArray: keyof MyInterface[] = ['keyOne', 'keyTwo']. Is there a simple way to get rid of this error?...
Read more >React components done right with TypeScript mapped and ...
The keyof T operator gets a union type of all the key names of the ... Exclude<T, U> – Exclude from T those...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
I changed the title of the issue since the core problem is that an intersection of complementary subsets of a higher order type, constructed using
Pick<T, K>
or by other means, is not assignable back to that higher order type.Meanwhile, investigating the issue revealed other issues, notably #29067 and #29081. I have fixed both, and with the fixes in place it is now possible to use a type assertion back to the higher order type. For example:
If and when we implement the improvement suggested by this issue the
as T
assertion in thewithDefaults
function becomes unnecessary.It seems this still not fixed in v3.4.0-dev.20190310