如何在打字稿中将具有动态 属性 名称的值分配给 class
How to assign value with dynamic property name to class in typescript
我写了一段代码,使用打字稿将 QueryArrayResult 映射到 deno 中的对象。
const mapDbResultToModelArray = <T>(dbResult: QueryArrayResult<Array<string>>): Array<T> => {
const objArr: Array<T> = [];
for (let i = 0; i < (dbResult.rowCount || 0); i++) {
const obj = {} as T;
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
//@ts-ignore
obj[columnInfo.name] = dbResult.rows[i][columnInfo.index - 1];
}
objArr[i] = obj;
}
return objArr;
}
但是这段代码有 //@ts-ignore
问题,我不能指望 return obj 的类型是 T。对象可以有 null 值
如何使用动态 属性 名称安全地分配值,例如 columnInfo.name
而没有 //@ts-ignore
如果您只是想绕过 ts-ignore,您可以做一些事情
- 使用绕过类型检查的函数
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
Object.assign(obj, {[columnInfo.name] : dbResult.rows[i][columnInfo.index - 1]});
}
- 转换为 T 的键
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
obj[columnInfo.name as keyof T] = dbResult.rows[i][columnInfo.index - 1];
}
- 由于您将数组转换为
Array<T>
,因此无需将 obj 转换为 T
const obj: any = {};
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
obj[columnInfo.name] = dbResult.rows[i][columnInfo.index - 1];
}
objArr[i] = obj;
解释发生了什么...
目前对T没有限制,说<T>
T可以是string
、number
、object
、Symbol
..等等。
您可以使用 extend
即对 T
添加限制。
<T extends object>
将确保 T 是类型 object
的后代。
注意:这不会解决您的问题。 extends
与 equals
不同。
即..在你原来的功能做
type T = Record<string, any>
const obj = {} as T;
也能解决您的问题。然而做
const mapDbResultToModelArray = <T extends Record<string, any>>(dbResult: QueryArrayResult<Array<string>>): Array<T> => {
const objArr: Array<T> = [];
for (let i = 0; i < (dbResult.rowCount || 0); i++) {
const obj = {} as T;
不会。您仍然会遇到索引错误。那是因为在前一个示例中 T
确实是 Record<string, any>
但在阶梯示例中 T
仅继承自 Record<string, any>
但仍然可以是更具体的类型,即。 T = Record<'key1', 'key2', any>
这就是为什么转换 obj[columnInfo.name as keyof T]
总是有效的原因,因为如果键是 string
那么 keyof T
将是 string
但如果键是 'key1' | 'key2'
那么 keyof T
将是 key1' | 'key2
所以即使您打字更好,您仍然可能遇到问题,但希望您能更好地理解它们。
当我开始使用 TS 时,这样的事情确实看起来很烦人,但随着时间的推移,通常调查这样的问题有助于你更深入地理解代码。 IE。即使您编写了代码并且知道发生了什么,这在 运行 时可能是正确的,但 ts 会突出显示如果犯了小错误可能会出错的地方。
所以不要气馁,要求获得更深入的了解。
我写了一段代码,使用打字稿将 QueryArrayResult 映射到 deno 中的对象。
const mapDbResultToModelArray = <T>(dbResult: QueryArrayResult<Array<string>>): Array<T> => {
const objArr: Array<T> = [];
for (let i = 0; i < (dbResult.rowCount || 0); i++) {
const obj = {} as T;
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
//@ts-ignore
obj[columnInfo.name] = dbResult.rows[i][columnInfo.index - 1];
}
objArr[i] = obj;
}
return objArr;
}
但是这段代码有 //@ts-ignore
问题,我不能指望 return obj 的类型是 T。对象可以有 null 值
如何使用动态 属性 名称安全地分配值,例如 columnInfo.name
而没有 //@ts-ignore
如果您只是想绕过 ts-ignore,您可以做一些事情
- 使用绕过类型检查的函数
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
Object.assign(obj, {[columnInfo.name] : dbResult.rows[i][columnInfo.index - 1]});
}
- 转换为 T 的键
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
obj[columnInfo.name as keyof T] = dbResult.rows[i][columnInfo.index - 1];
}
- 由于您将数组转换为
Array<T>
,因此无需将 obj 转换为 T
const obj: any = {};
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
obj[columnInfo.name] = dbResult.rows[i][columnInfo.index - 1];
}
objArr[i] = obj;
解释发生了什么...
目前对T没有限制,说<T>
T可以是string
、number
、object
、Symbol
..等等。
您可以使用 extend
即对 T
添加限制。
<T extends object>
将确保 T 是类型 object
的后代。
注意:这不会解决您的问题。 extends
与 equals
不同。
即..在你原来的功能做
type T = Record<string, any>
const obj = {} as T;
也能解决您的问题。然而做
const mapDbResultToModelArray = <T extends Record<string, any>>(dbResult: QueryArrayResult<Array<string>>): Array<T> => {
const objArr: Array<T> = [];
for (let i = 0; i < (dbResult.rowCount || 0); i++) {
const obj = {} as T;
不会。您仍然会遇到索引错误。那是因为在前一个示例中 T
确实是 Record<string, any>
但在阶梯示例中 T
仅继承自 Record<string, any>
但仍然可以是更具体的类型,即。 T = Record<'key1', 'key2', any>
这就是为什么转换 obj[columnInfo.name as keyof T]
总是有效的原因,因为如果键是 string
那么 keyof T
将是 string
但如果键是 'key1' | 'key2'
那么 keyof T
将是 key1' | 'key2
所以即使您打字更好,您仍然可能遇到问题,但希望您能更好地理解它们。
当我开始使用 TS 时,这样的事情确实看起来很烦人,但随着时间的推移,通常调查这样的问题有助于你更深入地理解代码。 IE。即使您编写了代码并且知道发生了什么,这在 运行 时可能是正确的,但 ts 会突出显示如果犯了小错误可能会出错的地方。
所以不要气馁,要求获得更深入的了解。