javascript - 打字稿以编程方式设置复杂对象属性值
问题描述
ReactJS 和 TypeScript。我的总体目标是创建一个单一的事件处理函数,该函数接受输入元素的名称(选择、输入等),并根据属性名称以及来自事件的值设置复杂对象的属性。
本质上,是这样的:
handleChange = idx => e => {
const { name, value } = e.target;
const rows = [...this.state.rows];
rows[idx] = {
[name]: value
};
this.setState({
rows
});
};
但是,就我而言,我使用的是 TypeScript,而且我还使用了一个相当复杂的对象。
这是一些测试代码:(参考在通用约束中使用类型参数)
export interface ITraveler {
id: number;
dob: Date;
tripCost: number;
firstName: string;
lastName: string;
}
export enum CoverageType {
Standard,
Plus,
}
export default interface IQuoteInfo {
country: string;
state: { fullname: string; abbreviation: string };
travelDates: {
fromDate: Date;
toDate: Date;
};
travelerInfo: ITraveler[];
paymentInfo: {
initialDate: Date;
finalDate: Date | null;
};
coverageType: CoverageType;
tripInfo: {
name: string;
program: string;
};
contactInfo: {
firstName: string;
lastName: string;
address1: string;
address2: string;
city: string;
state: string;
zip: string;
country: string;
phone: string;
email: string;
};
setQuoteInfo: (e: any) => void;
}
const initialQuoteInfo: IQuoteInfo = {
country: "USA",
state: {
fullname: "New York",
abbreviation: "NY",
},
travelDates: {
fromDate: new Date(2020, 10, 28),
toDate: new Date(2020, 10, 30),
},
travelerInfo: [
{ id: 1, dob: new Date(), tripCost: 0, firstName: "", lastName: "" },
],
paymentInfo: {
initialDate: new Date(),
finalDate: null,
},
coverageType: CoverageType.Standard,
tripInfo: {
name: "",
program: "Program Name",
},
contactInfo: {
firstName: "",
lastName: "",
address1: "",
address2: "",
city: "",
state: "",
zip: "",
country: "",
phone: "",
email: "",
},
setQuoteInfo: () => {},
};
const getProperty = <T, K extends keyof T>(obj: T, key: K) => {
return key;
};
const setProperty = <T, K extends keyof T>(obj: T, key: K, value: any) => {
obj[key] = value;
console.log("object is", obj);
};
setProperty(initialQuoteInfo, "country", "United Kingdom");
好的,那我的问题是什么?这可行,但我不知道如何为比键/值属性更深或更复杂的任何东西设置属性和值。例如,我将如何设置state
fullname
and abbreviation
?假设元素“name”是“state.fullname”,我会尝试这样做:
setProperty(initialQuoteInfo, "state.fullName", "Virginia");
打字稿抱怨:
'"state.fullName"' 类型的参数不可分配给 '"contactInfo" 类型的参数 | “国家” | “状态” | “旅行日期” | "旅行者信息" | "支付信息" | “覆盖类型” | "旅行信息" | "setQuoteInfo"'.ts(2345)
这有效:
setProperty(initialQuoteInfo, "state", {
fullname: "Virginia",
abbreviation: "VA",
});
我可以想到几种方法来临时管理这个问题。一种是解析“名称”,如果它有一个点,那么做一些时髦的设置。另一个可能是创建另一个函数,该函数接受解析后的名称,并与函数本质上做同样的事情setProperty
。
我不禁认为可能有一种更优雅、更实用的方法,因此我将不胜感激。
解决方案
function setProperty(obj: object, key: string, value: any) {
const propertyPath = key.split(".");
const propertyName = propertyPath.pop();
const baseObj = propertyPath.reduce((t: any, c) => t[c], obj);
baseObj[propertyName] = value;
}
经测试:
setProperty(initialQuoteInfo, "country", "United Kingdom");
setProperty(initialQuoteInfo, "state.fullname", "Virginia");
setProperty(initialQuoteInfo, "coverageType", CoverageType.Standard);
setProperty(initialQuoteInfo, "travelerInfo.0.dob", new Date(1980, 1, 1));
我承认它不符合您的“优雅和实用”标准,但它可以满足您的需求,并且很容易理解。
推荐阅读
- c++ - 在进程中对同一管道进行读取和写入时出现 C++ 管道问题
- vue.js - 在 Nuxt 从“spa”更改为“universal”,但我只得到未定义的文档
- php - 带有 bind_result() / fetch() mysqli 准备好的语句的 JSON 类型字段不起作用
- oracle - ORA-13029 - SDO_GEOMETRY 对象中的 SRID 无效
- javascript - 在选择选项之前出现框?
- c - C 程序找出二次方程的实根和复根 (ax^2 + bx + c = 0)
- javascript - 无法在 foreach 条件下使用 javascript 获取实时计算结果
- html - 尽管 z-index 内容超出了固定导航栏的顶部
- ios - 如何从 CIImage 中将 CVPixelBuffer 读取为 4 通道浮点格式?
- java - Java中列表中的项目分组