首页 > 解决方案 > 如何将具有动态属性名称的值分配给打字稿中的类

问题描述

我编写了一个代码,它使用 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一个问题,我不能指望返回 obj 的类型是 T。对象可以有空值

如何安全地分配具有动态属性名称的值,例如columnInfo.name没有//@ts-ignore

标签: typescriptpostgresqldeno

解决方案


如果您只是想绕过 ts-ignore,您可以执行以下操作

  1. 使用绕过类型检查的函数
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
   Object.assign(obj, {[columnInfo.name] : dbResult.rows[i][columnInfo.index - 1]});
}

  1. 强制转换为 T
for (let columnInfo of (dbResult.rowDescription || {columns:[]}).columns) {
   obj[columnInfo.name as keyof T] = dbResult.rows[i][columnInfo.index - 1];
}
  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.. 等。您可以T使用extendie 添加限制。 <T extends object>将确保 T 会从 type 下降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 会突出显示如果出现小错误可能会出错的地方。

因此,不要气馁,要求获得更深入的了解。


推荐阅读