是否可以使用像Object.assign(...)这样的复制操作来仅将已知属性复制到目标位置?

我的样例代码如下所示:

class A {
    foo?: string;
    constructor(p: any) {
        Object.assign(this, p);
    }
}

const instance = new A({
    foo: 'test',
    bar: 'other'
});

console.log(instance); // yields:     A: { "foo": "test", "bar": "other" }
                       // but i want: A: { "foo": "test" }

我知道JS中go 掉了类型,但我想知道在装饰符之类的东西中是否仍然可以这样做.

复选.hasOwnProperty或类似值不是一个选项,因为它应该允许复制未设置的属性,如上例所示.

推荐答案

Typescript 中没有反思或反省的概念.因此,一种方法是将元数据添加到您类型中,并使用您自己的Assign版本.

const MAPPED_TYPE_METADATA_KEY = Symbol('mappedType');
type TypeOfType = 'string' | 'number' | 'bigint' | 'boolean' | 'function' | 'object';

/** Decorator that adds mapped types to an object. */
function mappedType(typeName: TypeOfType) {
  return function(target: any, propertyKey: string): void {
    const typeMap = { ...Reflect.get(target, MAPPED_TYPE_METADATA_KEY), [propertyKey]: typeName };
    Reflect.set(target, MAPPED_TYPE_METADATA_KEY, typeMap);
    Reflect.defineMetadata(MAPPED_TYPE_METADATA_KEY, typeMap, target);
  };
}
/** Uses mappedTypes to assign values to an object. */ 
function customAssign<T>(obj: T, data: Partial<{ [key in keyof A]: A[key] }>): void {
  const typeMap: Record<string | number | symbol, TypeOfType> | undefined = Reflect.get(obj, MAPPED_TYPE_METADATA_KEY);
  if (typeMap) {
    Object.entries(data)
      .filter(([key, value]) => typeMap[key as keyof T] === typeof value)
      .forEach(([key, value]) => (obj as any)[key] = value);
  }
}
class A {
    @mappedType('string')
    foo?: string;
    @mappedType('number')
    another: number = 1; // added for testing

    constructor(data: any) {
      customAssign(this, data);
    }
}

const instance = new A({
    foo: 'test',
    bar: 'other'
}); 

console.log(instance);  // outputs {another: 1, foo: 'test'} // another defaults to 1 and not accidentally overwritten.

该解决方案包括以下功能.

  • 一个mapepdType的修饰符,它创建一个类型映射,该类型映射以字段名为键,并映射到值的类型.这里的危险在于,没有任何强制类型匹配的内容.
  • 一个customAssign函数,其作用类似于ASSIGN,但会 destruct 由修饰者创建的a _typeMap字段,以便正确赋值.
  • 构造函数中的Object.assign被替换为customAssign.

输出与您所需的输出相匹配.此外,默认情况下分配的值不会被覆盖.

Typescript相关问答推荐

在角形加载组件之前无法获取最新令牌

在Switch陈述中输入保护类

angular 17独立使用多个组件(例如两个组件)

类型{...}的TypeScript参数不能赋给类型为never的参数''

如何访问Content UI的DatePicker/中的sx props of year picker?'<>

Redux—Toolkit查询仅在不为空的情况下添加参数

如何将类型从变量参数转换为返回中的不同形状?

在TypeScrip中分配回调时,参数的分配方向与回调本身相反.为什么会这样呢?

如何将泛型对象作为返回类型添加到类型脚本中

在Typescript 中,有没有`index=unfined的速记?未定义:某个数组[索引]`?

按函数名的类型安全类型脚本方法包装帮助器

如何在Next.js和Tailwind.css中更改悬停时的字体 colored颜色

为什么类型脚本使用接口来声明函数?他的目的是什么.

Vite+Chrome扩展 list v3-;不能在模块外使用import语句;对于inpage脚本

传入类型参数<;T>;变容函数

在类型{}上找不到带有string类型参数的索引签名 - TypeScript

如何让Record中的每个值都有独立的类型?

包含多个不同类构造函数的接口的正确类型?

根据索引将元组拆分为两个块

Next.JS-13(应用程序路由)中发现无效的中间件