[英]How to return a generic type in TypeScript
What I want to achieve:我想要实现的目标:
What I have tried:我试过的:
const createGUID = (): string => {
return "";
};
const callService = (path: string, payload: Payload): void => {
//
};
type Payload = {
id: string;
timeStemp: number;
asyncCall: boolean;
};
function createPayloadWithData<T extends Payload>(
id: string,
asyncCall: boolean,
data?: {}
): T {
let ts = Date.now();
let payload = { id, asyncCall, timeStemp: ts, ...data };
return payload; "//<--- TS error: { id: string; asyncCall: boolean; timeStemp: number; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'Payload
}"
const registerUser = (username: string) => {
const userId = createGUID();
const payload = createPayloadWithData(userId, false, { username });
callService("users", payload);
};
const updateRecords = (records: number[]) => {
const recordsId = createGUID();
const payload = createPayloadWithData(recordsId, true, { records });
callService("records", payload);
};
registerUser("john");
updateRecords([1, 2, 3]);
(In sandbox: https://codesandbox.io/s/ecstatic-bas-97ucu?file=/src/index.ts ) (在沙盒中: https://codesandbox.io/s/ecstatic-bas-97ucu?file=/src/index.ts )
TS throws an error for the return value of createPayloadWithData. TS针对createPayloadWithData的返回值抛出错误。 Please allow me to say that I know WHY it does not work.请允许我说我知道为什么它不起作用。 I understand the logic and I have read the wonderful explanation here: could be instantiated with a different subtype of constraint 'object'我理解其中的逻辑,并且在这里阅读了精彩的解释: 可以使用约束“对象”的不同子类型进行实例化
What I don't understand, is how to do it correctly.我不明白的是如何正确地做到这一点。 Would really appreciate your help.非常感谢您的帮助。 Thanks!谢谢!
The problem here is that generic defined like that: T extends Payload
.这里的问题是泛型定义如下: T extends Payload
。
It means T
can contain more properties but id
, timeStemp
and async
for sure and returned T
has to respect it.这意味着T
可以包含更多属性,但id
、 timeStemp
和async
是肯定的,返回的T
必须遵守它。
type PayloadMore = Payload & {required: boolean};
const result: PayloadMore = createPayloadWithData<PayloadMore>('', false);
// but it won't work because `required` isn't present in the return value.
The way you need to do it is to move data
as generic and unite it in the return您需要做的是将data
作为通用数据移动并将其合并到返回中
const createGUID = (): string => {
return "";
};
const callService = (path: string, payload: Payload): void => {
//
};
type Payload = {
id: string;
timeStemp: number;
async: boolean;
};
// optional case
function createPayloadWithData(
id: string,
async: boolean
): Payload;
// case with data
function createPayloadWithData<T extends object>(
id: string,
async: boolean,
data: T
): Payload & T;
// implementation
function createPayloadWithData(
id: string,
async: boolean,
data?: {}
): Payload {
let ts = Date.now();
let payload = { id, async, timeStemp: ts, ...data };
return payload;
}
const registerUser = (username: string) => {
const userId = createGUID();
const payload = createPayloadWithData(userId, false, { username });
payload.username // <- now it works
callService("users", payload);
};
const updateRecords = (records: number[]) => {
const recordsId = createGUID();
const payload = createPayloadWithData(recordsId, true, { records });
payload.id // <- now it works
payload.records // <- now it works
callService("users", payload);
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.