如何在打字稿中将具有动态 属性 名称的值分配给 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,您可以做一些事情

  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可以是stringnumberobjectSymbol..等等。 您可以使用 extend 即对 T 添加限制。 <T extends object> 将确保 T 是类型 object 的后代。 注意:这不会解决您的问题。 extendsequals 不同。 即..在你原来的功能做

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 会突出显示如果犯了小错误可能会出错的地方。

所以不要气馁,要求获得更深入的了解。