Unassignable function return type when generated by a generic function generator in Typescript
up vote
1
down vote
favorite
When I run this code:
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter<T extends ConverterOutput>(
value: string,
type: 'number' | 'string'
): Converter<T> {
return (value: string): T => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
I get these 2 errors:
[ts] Type 'number' is not assignable to type 'T'. [2322]
[ts] Type 'string' is not assignable to type 'T'. [2322]
for the 2 switch ... case
returned values. I don't get what can be wrong in this code since T
extends ConverterOutput
which itself is a number | string
.
I have tried adding a generic catch: return <U extends T>(value: string): U => {
but it doesn't solve anything other than telling me that it's not assignable to U
this time.
typescript
add a comment |
up vote
1
down vote
favorite
When I run this code:
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter<T extends ConverterOutput>(
value: string,
type: 'number' | 'string'
): Converter<T> {
return (value: string): T => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
I get these 2 errors:
[ts] Type 'number' is not assignable to type 'T'. [2322]
[ts] Type 'string' is not assignable to type 'T'. [2322]
for the 2 switch ... case
returned values. I don't get what can be wrong in this code since T
extends ConverterOutput
which itself is a number | string
.
I have tried adding a generic catch: return <U extends T>(value: string): U => {
but it doesn't solve anything other than telling me that it's not assignable to U
this time.
typescript
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
When I run this code:
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter<T extends ConverterOutput>(
value: string,
type: 'number' | 'string'
): Converter<T> {
return (value: string): T => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
I get these 2 errors:
[ts] Type 'number' is not assignable to type 'T'. [2322]
[ts] Type 'string' is not assignable to type 'T'. [2322]
for the 2 switch ... case
returned values. I don't get what can be wrong in this code since T
extends ConverterOutput
which itself is a number | string
.
I have tried adding a generic catch: return <U extends T>(value: string): U => {
but it doesn't solve anything other than telling me that it's not assignable to U
this time.
typescript
When I run this code:
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter<T extends ConverterOutput>(
value: string,
type: 'number' | 'string'
): Converter<T> {
return (value: string): T => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
I get these 2 errors:
[ts] Type 'number' is not assignable to type 'T'. [2322]
[ts] Type 'string' is not assignable to type 'T'. [2322]
for the 2 switch ... case
returned values. I don't get what can be wrong in this code since T
extends ConverterOutput
which itself is a number | string
.
I have tried adding a generic catch: return <U extends T>(value: string): U => {
but it doesn't solve anything other than telling me that it's not assignable to U
this time.
typescript
typescript
asked Nov 20 at 14:51
Edouard Hienrichs
38211
38211
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
2
down vote
accepted
Typescript will not let you assign concrete values where a value of a generic type parameter is expected. The reason for this is that usually the value can't be validated against all possible derived types that could conceivable be passed for the generic type parameter. For example even in your case, T extends number| string
so this mean it could be the number literal type 1
which would not be satisfied by the value Number(value)
.
In your case I would recommend doing away with the generic type parameters and use multiple overloads, with the implementation signature returning Converter<number | string>
. This has the added benefit that the type of the converter will only need to be specified as a string not as both string and type parameter.
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter(value: string, type: 'number'): Converter<number>
function generateConverter(value: string, type: 'string'): Converter<string>
function generateConverter(value: string, type: 'number' | 'string'): Converter<number | string> {
return (value) => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
add a comment |
up vote
1
down vote
Because a number
nor a string
does not extend itself. That's why it's not working. You can fix it by giving the type directly e.g.
function generateConverter(value: string, type: 'number' | 'string'): Converter<ConverterOutput> {
return (value: string): ConverterOutput => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
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%2f53395619%2funassignable-function-return-type-when-generated-by-a-generic-function-generator%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
2
down vote
accepted
Typescript will not let you assign concrete values where a value of a generic type parameter is expected. The reason for this is that usually the value can't be validated against all possible derived types that could conceivable be passed for the generic type parameter. For example even in your case, T extends number| string
so this mean it could be the number literal type 1
which would not be satisfied by the value Number(value)
.
In your case I would recommend doing away with the generic type parameters and use multiple overloads, with the implementation signature returning Converter<number | string>
. This has the added benefit that the type of the converter will only need to be specified as a string not as both string and type parameter.
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter(value: string, type: 'number'): Converter<number>
function generateConverter(value: string, type: 'string'): Converter<string>
function generateConverter(value: string, type: 'number' | 'string'): Converter<number | string> {
return (value) => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
add a comment |
up vote
2
down vote
accepted
Typescript will not let you assign concrete values where a value of a generic type parameter is expected. The reason for this is that usually the value can't be validated against all possible derived types that could conceivable be passed for the generic type parameter. For example even in your case, T extends number| string
so this mean it could be the number literal type 1
which would not be satisfied by the value Number(value)
.
In your case I would recommend doing away with the generic type parameters and use multiple overloads, with the implementation signature returning Converter<number | string>
. This has the added benefit that the type of the converter will only need to be specified as a string not as both string and type parameter.
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter(value: string, type: 'number'): Converter<number>
function generateConverter(value: string, type: 'string'): Converter<string>
function generateConverter(value: string, type: 'number' | 'string'): Converter<number | string> {
return (value) => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
add a comment |
up vote
2
down vote
accepted
up vote
2
down vote
accepted
Typescript will not let you assign concrete values where a value of a generic type parameter is expected. The reason for this is that usually the value can't be validated against all possible derived types that could conceivable be passed for the generic type parameter. For example even in your case, T extends number| string
so this mean it could be the number literal type 1
which would not be satisfied by the value Number(value)
.
In your case I would recommend doing away with the generic type parameters and use multiple overloads, with the implementation signature returning Converter<number | string>
. This has the added benefit that the type of the converter will only need to be specified as a string not as both string and type parameter.
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter(value: string, type: 'number'): Converter<number>
function generateConverter(value: string, type: 'string'): Converter<string>
function generateConverter(value: string, type: 'number' | 'string'): Converter<number | string> {
return (value) => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
Typescript will not let you assign concrete values where a value of a generic type parameter is expected. The reason for this is that usually the value can't be validated against all possible derived types that could conceivable be passed for the generic type parameter. For example even in your case, T extends number| string
so this mean it could be the number literal type 1
which would not be satisfied by the value Number(value)
.
In your case I would recommend doing away with the generic type parameters and use multiple overloads, with the implementation signature returning Converter<number | string>
. This has the added benefit that the type of the converter will only need to be specified as a string not as both string and type parameter.
type Converter<T extends ConverterOutput> = (value: string) => T
type ConverterOutput = number | string
function generateConverter(value: string, type: 'number'): Converter<number>
function generateConverter(value: string, type: 'string'): Converter<string>
function generateConverter(value: string, type: 'number' | 'string'): Converter<number | string> {
return (value) => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
answered Nov 20 at 15:03
Titian Cernicova-Dragomir
55.5k33351
55.5k33351
add a comment |
add a comment |
up vote
1
down vote
Because a number
nor a string
does not extend itself. That's why it's not working. You can fix it by giving the type directly e.g.
function generateConverter(value: string, type: 'number' | 'string'): Converter<ConverterOutput> {
return (value: string): ConverterOutput => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
add a comment |
up vote
1
down vote
Because a number
nor a string
does not extend itself. That's why it's not working. You can fix it by giving the type directly e.g.
function generateConverter(value: string, type: 'number' | 'string'): Converter<ConverterOutput> {
return (value: string): ConverterOutput => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
add a comment |
up vote
1
down vote
up vote
1
down vote
Because a number
nor a string
does not extend itself. That's why it's not working. You can fix it by giving the type directly e.g.
function generateConverter(value: string, type: 'number' | 'string'): Converter<ConverterOutput> {
return (value: string): ConverterOutput => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
Because a number
nor a string
does not extend itself. That's why it's not working. You can fix it by giving the type directly e.g.
function generateConverter(value: string, type: 'number' | 'string'): Converter<ConverterOutput> {
return (value: string): ConverterOutput => {
switch (type) {
case 'number':
return Number(value)
default:
return value
}
}
}
answered Nov 20 at 15:03
Murat Karagöz
14.1k53267
14.1k53267
add a comment |
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53395619%2funassignable-function-return-type-when-generated-by-a-generic-function-generator%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