英文:
Typescript: type error emerged on creating a "copy" constructor for class
问题
I would like to add a constructor to MyClass which takes 2 parameters, first one is instance of MyClass and second one is partial of MyClass non-function properties. Example is I have below MyClass
我想在MyClass中添加一个构造函数,该构造函数接受2个参数,第一个是MyClass的实例,第二个是MyClass的非函数属性的部分。示例是我有以下的MyClass:
class MyClass {
public variable1: string | undefined;
public variable2: number | undefined;
public function1(): void {
console.log("log from function1.");
}
constructor(variable1: string, variable2: number) {
this.variable1 = p1;
this.variable2 = p2;
}
}
and
const instance1 = new MyClass("a", 1);
const instance2 = new MyClass(instance1, { variable1: "b" }); <= now instance2 is instance with variable1 as "b" and variable2 remains 1
以及
const instance1 = new MyClass("a", 1);
const instance2 = new MyClass(instance1, { variable1: "b" }); <= 现在instance2是一个具有variable1为"b"和variable2保持为1的实例
I changed MyClass as below
我将MyClass更改如下:
type PickByValue<T, ValueType> = Pick<T, {
[Key in keyof T]-?: T[Key] extends ValueType ? never : Key;
}[keyof T]>;
type NonFunction = PickByValue<MyClass, Function>;
type UUKeys = keyof NonFunction;
class MyClass {
public variable1: string | undefined;
public variable2: number | undefined;
public function1(): void {
console.log(this.variable1 ?? "variable missing " + this.variable2?.toString() ?? "variable2 missing");
}
// First constructor
constructor(variable1: string, variable2: number);
// Second constructor
constructor(p1: MyClass, p2: Partial<NonFunction>);
// Implementation
constructor(p1: MyClass | string, p2?: Partial<NonFunction> | number) {
if (typeof p1 === 'string' && typeof p2 === 'number') {
this.variable1 = p1;
this.variable2 = p2;
} else if (p1 instanceof MyClass && p2 && typeof p2 !== "number" && p2 satisfies Partial<NonFunction>) {
for (const key of Object.keys(p1)) {
if (typeof p1[key as keyof MyClass] !== "function") {
const k = key as UUKeys;
this[k] = p2[k] ?? p1[k];
^^^^^^ <= ERROR: Type 'string | number | undefined' is not assignable to type 'undefined'. Type 'string' is not assignable to type 'undefined'.
}
}
} else {
this.variable1 = '';
this.variable2 = 0;
}
}
}
Error emerged confused my which I could not understand where undefined coming from as I already exclude undefined by converting key to UUKeys.
错误出现混淆了我,我无法理解undefined来自哪里,因为我已经通过将key转换为UUKeys来排除了undefined。
Type 'string | number | undefined' is not assignable to type
'undefined'. Type 'string' is not assignable to type 'undefined'.
类型'string | number | undefined'不能赋值给类型'undefined'。类型'string'不能赋值给类型'undefined'。
BTW, I am using Typescript v5.1.6.
顺便说一下,我正在使用Typescript v5.1.6。
英文:
I would like to add a constructor to MyClass which takes 2 parameters, first one is instance of MyClass and second one is partial of MyClass non-function properties. Example is I have below MyClass
class MyClass {
public variable1: string | undefined;
public variable2: number | undefined;
public function1(): void {
console.log("log from function1.");
}
constructor(variable1: string, variable2: number) {
this.variable1 = p1;
this.variable2 = p2;
}
}
and
const instance1 = new MyClass("a", 1);
const instance2 = new MyClass(instance1, { variable1: "b" }); <= now instance2 is instance with variable1 as "b" and variable2 remains 1
I changed MyClass as below
type PickByValue<T, ValueType> = Pick<T, {
[Key in keyof T]-?: T[Key] extends ValueType ? never : Key;
}[keyof T]>;
type NonFunction = PickByValue<MyClass, Function>;
type UUKeys = keyof NonFunction;
class MyClass {
public variable1: string | undefined;
public variable2: number | undefined;
public function1(): void {
console.log(this.variable1 ?? "variable missing " + this.variable2?.toString() ?? "variable2 missing");
}
// First constructor
constructor(variable1: string, variable2: number);
// Second constructor
constructor(p1: MyClass, p2: Partial<NonFunction>);
// Implementation
constructor(p1: MyClass | string, p2?: Partial<NonFunction> | number) {
if (typeof p1 === 'string' && typeof p2 === 'number') {
this.variable1 = p1;
this.variable2 = p2;
} else if (p1 instanceof MyClass && p2 && typeof p2 !== "number" && p2 satisfies Partial<NonFunction>) {
for (const key of Object.keys(p1)) {
if (typeof p1[key as keyof MyClass] !== "function") {
const k = key as UUKeys;
this[k] = p2[k] ?? p1[k];
^^^^^^ <= ERROR: Type 'string | number | undefined' is not assignable to type 'undefined'. Type 'string' is not assignable to type 'undefined'.
}
}
} else {
this.variable1 = '';
this.variable2 = 0;
}
}
}
Error emerged confused my which I could not understand where undefined coming from as I already exclude undefined by converting key to UUKeys.
> Type 'string | number | undefined' is not assignable to type
> 'undefined'. Type 'string' is not assignable to type 'undefined'
BTW, I am using Typescript v5.1.6.
答案1
得分: 1
只返回翻译好的部分:
这会更有意义,如果我们看一下键 k 的类型和值 v。
if (typeof p1[key as keyof MyClass] !== 'function') {
const k = key as UUKeys; // 'variable1' | 'variable2'
const v = p2[k] ?? p1[k]; // number | string | undefined
this[k] = v;
}
- 键的类型是该类的属性的枚举(不是函数)。
- 值的类型是该类的所有(非函数)属性的类型的联合。在这种情况下,该值可以是数字、字符串或未定义。
如果键是 variable1,并且值是数字,则它将无效。如果键是 variable2,并且值是字符串,它也将无效。所有属性的唯一有效值是 undefined。
在这种情况下,您已经确定值具有正确的键类型,因为 p2 是 MyClass 的部分。
这是一个典型的情况,称为“我知道我在做什么”。减少类型检查。
(this as any)[key] = p2[key] ?? p1[key];
英文:
It makes more sense if we look at the type of the key k and the value v.
if (typeof p1[key as keyof MyClass] !== 'function') {
const k = key as UUKeys; // 'variable1' | 'variable2'
const v = p2[k] ?? p1[k]; // number | string | undefined
this[k] = v;
}
- The key type is an enum of the properties of the class (that's not a function).
- The value type is a union of the types of all (non-function) properties of the class. In this case, the value can either be a number, string, or undefined.
If the key is variable1 and the value is a number, it would be invalid. If the key is variable2 and the value is a string, it would also be invalid. The only valid value for all properties is undefined.
In this case, you're already sure that the value has the correct type for the key, because p2 is a partial of MyClass.
This is a typical case of "I know what I'm doing". Ease down on the type-checking.
(this as any)[key] = p2[key] ?? p1[key];
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论