gpt4 book ai didi

TypeScript 将对象从具有可选属性的类型转换为不具有可选属性的类型

转载 作者:行者123 更新时间:2023-12-05 06:17:13 24 4
gpt4 key购买 nike

我是 TypeScript 的新手,我正面临一个非常微不足道的问题。我正在使用第三方电子邮件库,它包含在我控制的服务功能中。第三方功能以及我的服务功能接受具有通用电子邮件配置属性(收件人、发件人、主题、正文...)的对象,但第三方功能需要所有这些,而我的服务让 from 属性是可选的。见下文。

// Third Party Code

type ThirdPartyEmailData = {
from: string;
to: string;
subject: string;
body: string;
}

const sendEmailWithThirdPartyService = (emailData: ThirdPartyEmailData) => {

console.log('Sending email from:', emailData);

}

-----------------------------------------------------------------------------

// My Code

type MyEmailData = {
from?: string;
to: string;
subject: string;
body: string;
}

const sendEmail = (emailData: MyEmailData) => {

emailData = { from: 'info@company.com', ...emailData };

sendEmailWithThirdPartyService(emailData); // This does not compile

/**
* Argument of type 'MyEmailData' is not assignable to parameter of type 'ThirdPartyEmailData'.
* Property 'from' is optional in type 'MyEmailData' but required in type 'ThirdPartyEmailData'.
*/

}

sendEmail({
to: 'john.doe@customer.com',
subject: 'I <3 TypeScript',
body: 'But TypeScript hates me'
});

正如预期的那样,上面的代码无法编译,因为“MyEmailData”类型不能分配给“ThirdPartyEmailData”类型的参数。我一直在寻找一种干净的方法来转换/更改/转换 emailData 的类型,然后再将其传递给第三方函数,但我真的找不到好的方法。以下是我想到的一些东西,但感觉不太好。

方案一:直接转第三方类型

// My Code

const sendEmail = (emailData: MyEmailData) => {

// If you remove the line below the program still compiles but breaks at runtime
emailData = { from: 'info@company.com', ...emailData };

sendEmailWithThirdPartyService(<ThirdPartyEmailData>emailData); // This compiles

}

解决方案 2:使用类型保护来确保存在 from 属性

// My Code

const sendEmail = (emailData: MyEmailData) => {

emailData = { from: 'info@company.com', ...emailData };

// By using the type guard, we ensure that the type of emailData overlaps ThirdPartyEmailData
if (! hasFromProperty(emailData)) throw new Error('From property is missing');

sendEmailWithThirdPartyService(emailData); // This compiles

}

-----------------------------------------------------------------------------

// Utilities

/** Utility to make certain keys of a type required */
type RequiredKeys<T, K extends keyof T> = Exclude<T, K> & Required<Pick<T, K>>

/** Typeguard for property 'from' in MyEmailData */
const hasFromProperty = (data: MyEmailData): data is RequiredKeys<MyEmailData, 'from'> => {

return 'from' in data;

}

这看起来是一个非常普遍的问题,但我一直未能找到令人满意的解决方案。你能推荐什么?

最佳答案

你应该避免改变参数。对于您的情况,解决方案很简单:

const sendEmail = (emailData: MyEmailData) => {
const thirdPartyEmailData: ThirdPartyEmailData = { from: 'info@company.com', ...emailData };
sendEmailWithThirdPartyService(thirdPartyEmailData);
}

即使不声明 thirdPartyEmailData const thirdPartyEmailData = { from: 'info@company.com', ...emailData }; 因为它是推断的类型,它也能工作。

关于TypeScript 将对象从具有可选属性的类型转换为不具有可选属性的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61726122/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com