打字稿遍历打字稿对象:界面但继续打字
Typescript itterate through typescript object : interface but keep typing
我有一个方法,它接受一个对象,它是一个部分我想使用 Object.entries 遍历该对象,然后基于我想执行一些操作的键。该接口的键是字符串,而值是字符串|数字|字符串[]|日期时间。我希望传递给它的函数知道从密钥传入的是什么。
我目前的密码是
public partialUpdate = async (id: number, fieldsToUpdate: Partial<IClient>) => {
type temp = Partial<Record<keyof IClient, (val : string) => void>>;
const mapping : temp = {
name: (val) => client.setName(val),
website: (val) => client.setWebsite(val),
sic_codes: (val) => client.setSicCodes(val),
phone_number: (val) => client.setPhoneNumber(val),
};
Object.entries(fieldsToUpdate).forEach(([key, value]) => mapping[key](value));
return this.clientRepository.update(id, client);
};
界面是
export interface IClient
{
id: number,
creation_date: DateTime,
name:string,
website:string,
phone_number:string,
industry:string,
sic_codes:string[],
}
我目前遇到的问题是,如果它都是字符串类型,那么没有问题,但是因为 sic_codes 是一个字符串[],它会导致类型错误。有什么方法可以让 const 映射知道键中的 val 类型?
你原来的类型
Record<keyof IClient, (val: string) => void>
使用 the Record<K, V>
utility type, which is implemented as a mapped type。让我们根据映射类型明确地写出来:
{[K in keyof IClient]: (val: string) => void}
所以,这里的问题是 val
类型 string
不一定是 keyof IClient
中每个键 K
的值类型 IClient
.修复方法是将 string
替换为 IClient[K]
,indexed access type 表示“键 K
处 IClient
的值类型”:
type Test = { [K in keyof IClient]: (val: IClient[K]) => void };
/* type Test = {
id: (val: number) => void;
creation_date: (val: Date) => void;
name: (val: string) => void;
company_number: (val: string) => void;
website: (val: string) => void;
phone_number: (val: string) => void;
industry: (val: string) => void;
sic_codes: (val: string[]) => void;
} */
看起来不错。
如果我们将其插入到您使用原始类型的位置,仍然存在错误。 Object.entries()
的类型不够强,无法满足您在 TypeScript 中的需求。请参阅您正在处理的特定密钥类型 K
中的 for more information. You can give it stronger typings (even though this isn't 100% safe). Even if you do that, your forEach()
callback needs to be generic。在那个回调中你需要确保你的 value
和你的 mapping[key]
不是 undefined
,如果你想安全的话:
让我进行这些更改,只是为了证明它按您的预期工作:
// Give stronger typings to Object.entries()
type Entry<T extends object> = { [K in keyof T]-?: [K, T[K]] }[keyof T];
function entries<T extends object>(obj: T) {
return Object.entries(obj) as Entry<T>[];
}
const partialUpdate = async (id: number, fieldsToUpdate: Partial<IClient>) => {
const client = new Client();
const mapping: Partial<{ [K in keyof IClient]: (val: IClient[K]) => void }> = {
name: (val) => client.setName(val),
company_number: (val) => client.setCompanyNumber(val),
industry: (val) => client.setIndustry(val),
sic_codes: (val) => client.setSicCodes(val),
};
const e = entries(fieldsToUpdate).forEach(<K extends keyof IClient>(
[key, value]: [K, IClient[K] | undefined]) => value && mapping[key]?.(value));
return null;
};
万岁,没有错误!
我有一个方法,它接受一个对象,它是一个部分我想使用 Object.entries 遍历该对象,然后基于我想执行一些操作的键。该接口的键是字符串,而值是字符串|数字|字符串[]|日期时间。我希望传递给它的函数知道从密钥传入的是什么。
我目前的密码是
public partialUpdate = async (id: number, fieldsToUpdate: Partial<IClient>) => {
type temp = Partial<Record<keyof IClient, (val : string) => void>>;
const mapping : temp = {
name: (val) => client.setName(val),
website: (val) => client.setWebsite(val),
sic_codes: (val) => client.setSicCodes(val),
phone_number: (val) => client.setPhoneNumber(val),
};
Object.entries(fieldsToUpdate).forEach(([key, value]) => mapping[key](value));
return this.clientRepository.update(id, client);
};
界面是
export interface IClient
{
id: number,
creation_date: DateTime,
name:string,
website:string,
phone_number:string,
industry:string,
sic_codes:string[],
}
我目前遇到的问题是,如果它都是字符串类型,那么没有问题,但是因为 sic_codes 是一个字符串[],它会导致类型错误。有什么方法可以让 const 映射知道键中的 val 类型?
你原来的类型
Record<keyof IClient, (val: string) => void>
使用 the Record<K, V>
utility type, which is implemented as a mapped type。让我们根据映射类型明确地写出来:
{[K in keyof IClient]: (val: string) => void}
所以,这里的问题是 val
类型 string
不一定是 keyof IClient
中每个键 K
的值类型 IClient
.修复方法是将 string
替换为 IClient[K]
,indexed access type 表示“键 K
处 IClient
的值类型”:
type Test = { [K in keyof IClient]: (val: IClient[K]) => void };
/* type Test = {
id: (val: number) => void;
creation_date: (val: Date) => void;
name: (val: string) => void;
company_number: (val: string) => void;
website: (val: string) => void;
phone_number: (val: string) => void;
industry: (val: string) => void;
sic_codes: (val: string[]) => void;
} */
看起来不错。
如果我们将其插入到您使用原始类型的位置,仍然存在错误。 Object.entries()
的类型不够强,无法满足您在 TypeScript 中的需求。请参阅您正在处理的特定密钥类型 K
中的 forEach()
callback needs to be generic。在那个回调中你需要确保你的 value
和你的 mapping[key]
不是 undefined
,如果你想安全的话:
让我进行这些更改,只是为了证明它按您的预期工作:
// Give stronger typings to Object.entries()
type Entry<T extends object> = { [K in keyof T]-?: [K, T[K]] }[keyof T];
function entries<T extends object>(obj: T) {
return Object.entries(obj) as Entry<T>[];
}
const partialUpdate = async (id: number, fieldsToUpdate: Partial<IClient>) => {
const client = new Client();
const mapping: Partial<{ [K in keyof IClient]: (val: IClient[K]) => void }> = {
name: (val) => client.setName(val),
company_number: (val) => client.setCompanyNumber(val),
industry: (val) => client.setIndustry(val),
sic_codes: (val) => client.setSicCodes(val),
};
const e = entries(fieldsToUpdate).forEach(<K extends keyof IClient>(
[key, value]: [K, IClient[K] | undefined]) => value && mapping[key]?.(value));
return null;
};
万岁,没有错误!