How to write omit function with proper types in typescript
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>>
reactjs typescript
add a comment |
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>>
reactjs typescript
add a comment |
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>>
reactjs typescript
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>>
reactjs typescript
reactjs typescript
asked Nov 25 '18 at 9:17
aocenasaocenas
5117
5117
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
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
Thank you very much, this helps tremendously. I realised thought I have one more piece in the HOC, that I omitted in the question. Would it be possible to back propagate theA
type somehow to the first function call. What I want to do is<B extends keyof any>(arg: B, fn: (arg: A) => void) => ...
. So basically, I give you attribute name and a function that will take object I will give you later. If that does not make sense I can create new question, my bad I did not realise this will be important.
– aocenas
Nov 25 '18 at 18:08
@aocenas could you post a new question with the full code ? It would make more sense to see it in full.. the comments is not a good place for a lot of code..
– Titian Cernicova-Dragomir
Nov 25 '18 at 18:10
Here is the new question, hope it makes sense stackoverflow.com/questions/53470559/…
– aocenas
Nov 25 '18 at 18:32
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53466131%2fhow-to-write-omit-function-with-proper-types-in-typescript%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
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
Thank you very much, this helps tremendously. I realised thought I have one more piece in the HOC, that I omitted in the question. Would it be possible to back propagate theA
type somehow to the first function call. What I want to do is<B extends keyof any>(arg: B, fn: (arg: A) => void) => ...
. So basically, I give you attribute name and a function that will take object I will give you later. If that does not make sense I can create new question, my bad I did not realise this will be important.
– aocenas
Nov 25 '18 at 18:08
@aocenas could you post a new question with the full code ? It would make more sense to see it in full.. the comments is not a good place for a lot of code..
– Titian Cernicova-Dragomir
Nov 25 '18 at 18:10
Here is the new question, hope it makes sense stackoverflow.com/questions/53470559/…
– aocenas
Nov 25 '18 at 18:32
add a comment |
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
Thank you very much, this helps tremendously. I realised thought I have one more piece in the HOC, that I omitted in the question. Would it be possible to back propagate theA
type somehow to the first function call. What I want to do is<B extends keyof any>(arg: B, fn: (arg: A) => void) => ...
. So basically, I give you attribute name and a function that will take object I will give you later. If that does not make sense I can create new question, my bad I did not realise this will be important.
– aocenas
Nov 25 '18 at 18:08
@aocenas could you post a new question with the full code ? It would make more sense to see it in full.. the comments is not a good place for a lot of code..
– Titian Cernicova-Dragomir
Nov 25 '18 at 18:10
Here is the new question, hope it makes sense stackoverflow.com/questions/53470559/…
– aocenas
Nov 25 '18 at 18:32
add a comment |
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
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
edited Nov 25 '18 at 10:04
answered Nov 25 '18 at 9:57
Titian Cernicova-DragomirTitian Cernicova-Dragomir
67.6k34664
67.6k34664
Thank you very much, this helps tremendously. I realised thought I have one more piece in the HOC, that I omitted in the question. Would it be possible to back propagate theA
type somehow to the first function call. What I want to do is<B extends keyof any>(arg: B, fn: (arg: A) => void) => ...
. So basically, I give you attribute name and a function that will take object I will give you later. If that does not make sense I can create new question, my bad I did not realise this will be important.
– aocenas
Nov 25 '18 at 18:08
@aocenas could you post a new question with the full code ? It would make more sense to see it in full.. the comments is not a good place for a lot of code..
– Titian Cernicova-Dragomir
Nov 25 '18 at 18:10
Here is the new question, hope it makes sense stackoverflow.com/questions/53470559/…
– aocenas
Nov 25 '18 at 18:32
add a comment |
Thank you very much, this helps tremendously. I realised thought I have one more piece in the HOC, that I omitted in the question. Would it be possible to back propagate theA
type somehow to the first function call. What I want to do is<B extends keyof any>(arg: B, fn: (arg: A) => void) => ...
. So basically, I give you attribute name and a function that will take object I will give you later. If that does not make sense I can create new question, my bad I did not realise this will be important.
– aocenas
Nov 25 '18 at 18:08
@aocenas could you post a new question with the full code ? It would make more sense to see it in full.. the comments is not a good place for a lot of code..
– Titian Cernicova-Dragomir
Nov 25 '18 at 18:10
Here is the new question, hope it makes sense stackoverflow.com/questions/53470559/…
– aocenas
Nov 25 '18 at 18:32
Thank you very much, this helps tremendously. I realised thought I have one more piece in the HOC, that I omitted in the question. Would it be possible to back propagate the
A
type somehow to the first function call. What I want to do is <B extends keyof any>(arg: B, fn: (arg: A) => void) => ...
. So basically, I give you attribute name and a function that will take object I will give you later. If that does not make sense I can create new question, my bad I did not realise this will be important.– aocenas
Nov 25 '18 at 18:08
Thank you very much, this helps tremendously. I realised thought I have one more piece in the HOC, that I omitted in the question. Would it be possible to back propagate the
A
type somehow to the first function call. What I want to do is <B extends keyof any>(arg: B, fn: (arg: A) => void) => ...
. So basically, I give you attribute name and a function that will take object I will give you later. If that does not make sense I can create new question, my bad I did not realise this will be important.– aocenas
Nov 25 '18 at 18:08
@aocenas could you post a new question with the full code ? It would make more sense to see it in full.. the comments is not a good place for a lot of code..
– Titian Cernicova-Dragomir
Nov 25 '18 at 18:10
@aocenas could you post a new question with the full code ? It would make more sense to see it in full.. the comments is not a good place for a lot of code..
– Titian Cernicova-Dragomir
Nov 25 '18 at 18:10
Here is the new question, hope it makes sense stackoverflow.com/questions/53470559/…
– aocenas
Nov 25 '18 at 18:32
Here is the new question, hope it makes sense stackoverflow.com/questions/53470559/…
– aocenas
Nov 25 '18 at 18:32
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53466131%2fhow-to-write-omit-function-with-proper-types-in-typescript%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown