英文:
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];
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论