Reputation: 131
What I ultimately want to do is to create a React HOC that would inject a property defined by a string and return a component without requiring the injected property. In essence though this boils down to a factory function returning an omit function.
As you can see in this example for some reason the type B ends up being 'never'.
const f = <A extends object, B extends keyof A>(arg: B) => (obj: A): Omit<A, B> => {
delete obj[arg]
return obj
}
// TS2345: Argument of type "test" is not assignable to parameter of type 'never'
const a = f('test')
const b = a({ test: 1})
const c = b.test
When I try keyof outside of generic parameter, it seem to be functioning better, but typescript does not infer the return type properly and I do not know how to type it as I do not know how to get the reference to the first string arg that could be used in Omit:
const f = <A extends object>(arg: keyof A) => (obj: A) => {
delete obj[arg]
return obj
}
const a = f('test')
const b = a({ test: 1 })
// Does not infer 'test' is no longer here
const c = b.test
For reference Omit is:
export type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
Upvotes: 1
Views: 3329
Reputation: 249716
Since the first function has both type arguments, typescript will try to infer both when that call happens and since there is no inference site for A
it will probably infer {}
for it, making B
never. The way to fix this, is to make B
and when the second call occurs infer A
, with the constraint that A
must have a B
key:
export type Omit<T, K> = Pick<T, Exclude<keyof T, K>>
const f = <B extends keyof any>(arg: B) => <A extends Record<B, any>>(obj: A): Omit<A, B> => {
delete obj[arg]
return obj
}
const a = f('test')
const b = a({ test: 1, other: ""})
const c = b.test; // error as expected
const c2 = b.other; // ok
Upvotes: 1