admin管理员组文章数量:1356450
I'm trying to build method generic in typescript and make it returns generic type but TS shows an error on it
export type DataGenerator<T> = <T>(props: {name: string}) => T;
const dataGenerator: DataGenerator<{city?: string}> = ({ name }) => {
return {
city: `${name}`
}
}
dataGenerator({name: "xxx"})
error:
Type '<T>({ name }: { name: string; }) => { city: string; }' is not assignable to type 'DataGenerator<{ city?: string | undefined; }>'.
Type '{ city: string; }' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to '{ city: string; }'.
Any help?
I'm trying to build method generic in typescript and make it returns generic type but TS shows an error on it
export type DataGenerator<T> = <T>(props: {name: string}) => T;
const dataGenerator: DataGenerator<{city?: string}> = ({ name }) => {
return {
city: `${name}`
}
}
dataGenerator({name: "xxx"})
error:
Type '<T>({ name }: { name: string; }) => { city: string; }' is not assignable to type 'DataGenerator<{ city?: string | undefined; }>'.
Type '{ city: string; }' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to '{ city: string; }'.
Any help?
Share Improve this question asked Apr 12, 2023 at 23:05 SuhaibSuhaib 271 silver badge6 bronze badges 9-
1
Is this just a typo? You’ve declared two type parameters of the same name; why? Presumably you mean
type DataGenerator<T> =(props: {name: string}) => T;
but if so then there’s nothing wrong anymore – jcalz Commented Apr 12, 2023 at 23:14 - It's working with the solution but it doesn't show an error if returns a different object like add extra key with city – Suhaib Commented Apr 12, 2023 at 23:56
-
That's a followup question and out of scope for the question as asked... and most likely a duplicate of this. So what should we do here... close the question as cause by a typo? Or should I write up an explanation for why you need to remove the second
<T>
for it to work? – jcalz Commented Apr 13, 2023 at 0:49 -
export type DataGenerator<T> = (props: {name: string}) => T; const dataGenerator: DataGenerator<{city?: string}> = ({ name })=> { return { city: "", postCode: "aaa", } } dataGenerator({name: "xxx"})
– Suhaib Commented Apr 13, 2023 at 0:55 - why accept "postCode" here? as you see the object should has city only – Suhaib Commented Apr 13, 2023 at 0:56
1 Answer
Reset to default 8There are two different kinds of generics in TypeScript.
On the one hand there are generic types, where the generic type parameter is declared on the name of the type:
type GenTypeAlias<T> = T | number;
interface GenInterface<T> { prop: T }
class GenClass<T> { prop: T[] = [] }
where in order to talk about a value of that type you need to specify the type parameter with a type argument:
type SpecificTypeAlias = GenTypeAlias<string>; // okay
interface SpecificInterface extends GenInterface<number> { }; // okay
class SpecificClass extends GenClass<boolean> { }; // okay
type Oops = GenTypeAlias; // error!
// -------> ~~~~~~~~~~~~
// Generic type 'GenTypeAlias' requires 1 type argument.
For generic types, type arguments are specified by the person supplying the value of that type; if the type is a function, the implementer specifies the type argument.
On the other hand, there are generic functions, where the generic type parameter is declared on the call signature:
declare function genFunc<T>(val: T): T[];
type GenFunction = <T>(val: T) => T[];
where you can talk about a value of that type without specifying the type parameter; instead, you only specify the type parameter with a type argument when you call the function:
const genFunc2 = genFunc; // don't specify here
declare const alsoGenFunc: GenFunction; // don't specify here
const strArr = genFunc<string>("abc"); // specify here
// const strArr: string[]
const numArr = genFunc<number>(123); // specify here
// const numArr: number[]
Note that much of the time the piler can infer the type argument for a generic function call, but it's still being specified at call time:
const boolArr = genFunc(true);
// function genFunc<boolean>(val: boolean): boolean[]
// const boolArr: boolean[]
For generic functions, type arguments are specified by the person consuming the value of that type; the caller specifies the type argument.
So let's look at your DataGenerator
definition:
type DataGenerator<T> = <T>(props: { name: string }) => T;
// -------------> ^^^
// 'T' is declared but its value is never read.
Hmm, this seems to be both a generic function and a generic type, and furthermore the same type parameter name T
is used for both of them. Depending on your IDE you might see that the first T
is grayed out, with a message that it has been declared but unused. The inner T
is shadowing or masking the outer one, so the outer one is essentially ignored:
type DataGenerator<T> = <T>(props: { name: string }) => T;
// ^-
本文标签:
版权声明:本文标题:javascript - Typescript generic: 'T' could be instantiated with an arbitrary type which could be unrelated - Sta 内容由网友自发贡献,该文观点仅代表作者本人,
转载请联系作者并注明出处:http://www.betaflare.com/web/1744045838a2581503.html,
本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论