为什么 class 中的 属性 不是只读的(打字稿)
Why property in class is not read only (Typescript)
为什么 属性 name in class PeronsImpl 不是只读的,我们可以将创建的对象重新分配给它?
interface Person {
readonly name: string;
}
interface Greeting extends Person {
greet(message: string): void;
}
class PersonImpl implements Greeting {
name: string;
age = 30;
constructor(n: string) {
this.name = n;
}
greet(message: string) {
console.log(message + ' ' + this.name);
}
}
let pers = new PersonImpl("maha");
console.log(`pers : ${pers.name}`);
pers.name = "maha2";
pers.greet("hello"); //hello maha2
Why property name in class PeronsImpl is not read only...
因为它被类型转换为 PersonImpl
而 而不是 Person
。如果你想 name
作为只读,你也必须在实现中做到这一点 or 变量 pers
应该被定义为类型 Person
.
class PersonImpl implements Greeting {
readonly name: string; // <-- added readonly
age = 30;
constructor(n: string) {
this.name = n;
}
或指定类型
let pers:Person = new PersonImpl("maha"); // <-- added :Person
这有两个部分:Class 属性不从 classes 或它们扩展的接口继承类型;和只读属性可以相互分配给可变属性,也可以从可变属性相互分配。
Class 属性不从 classes 或它们扩展的接口继承类型
当您编写 class Foo implements Bar {...}
时,编译器不会使用 Bar
来推断 Foo
的任何属性的类型。它的行为就好像 implements Bar
不存在一样,推断出 Foo
的所有类型的属性,然后只是 对照 Bar
检查 。例如:
interface Foo {
x: 0 | 1;
}
class Bar implements Foo {
x = 1; // error! x is inferred as number, not 0 | 1
}
这是一个错误,因为 class Bar { x = 1 }
只会为 x
推断出 number
,并且由于 number
不能分配给 0 | 1
,所以这是一个错误.这种行为让很多人感到惊讶和不愉快,并且有很多 GitHub 问题在这里要求更好的东西。请参阅 microsoft/TypeScript#10570 了解一个特别长期未解决的问题。
这意味着 PersonImpl
的 name
属性 是 string
类型,而不是 readonly
:
class PersonImpl implements Greeting {
name: string; // string, not readonly string
//...
}
只读属性可与可变属性相互赋值
第二个问题是,仅在属性 readonly
方面不同的类型被编译器认为是相互兼容的。您可以将 {readonly x: string}
分配给 {x: string}
,反之亦然,不会出错。请参阅 for more information about why that is, or see microsoft/TypeScript#13347 以了解要求对此进行更改的功能请求。
所以这意味着编译器不会发出 PersonImpl
的 name
属性 是可变的而 Greeting
是 readonly
的错误。这些类型不被认为是不兼容的。
把它们放在一起,你就会得到你在这里看到的怪异之处。您可能会愉快地假设 PersonImpl
的 name
属性 是 readonly
,然后当您被允许为其赋值时会感到困惑。
这里的修复是 class 继承的打字问题的一般解决方法;为您的属性提供显式类型注释和修饰符:
class PersonImpl implements Greeting {
readonly name: string; // annotate with readonly
/* ... */
}
let pers = new PersonImpl("maha");
pers.name = "maha2"; // error
为什么 属性 name in class PeronsImpl 不是只读的,我们可以将创建的对象重新分配给它?
interface Person {
readonly name: string;
}
interface Greeting extends Person {
greet(message: string): void;
}
class PersonImpl implements Greeting {
name: string;
age = 30;
constructor(n: string) {
this.name = n;
}
greet(message: string) {
console.log(message + ' ' + this.name);
}
}
let pers = new PersonImpl("maha");
console.log(`pers : ${pers.name}`);
pers.name = "maha2";
pers.greet("hello"); //hello maha2
Why property name in class PeronsImpl is not read only...
因为它被类型转换为 PersonImpl
而 而不是 Person
。如果你想 name
作为只读,你也必须在实现中做到这一点 or 变量 pers
应该被定义为类型 Person
.
class PersonImpl implements Greeting {
readonly name: string; // <-- added readonly
age = 30;
constructor(n: string) {
this.name = n;
}
或指定类型
let pers:Person = new PersonImpl("maha"); // <-- added :Person
这有两个部分:Class 属性不从 classes 或它们扩展的接口继承类型;和只读属性可以相互分配给可变属性,也可以从可变属性相互分配。
Class 属性不从 classes 或它们扩展的接口继承类型
当您编写 class Foo implements Bar {...}
时,编译器不会使用 Bar
来推断 Foo
的任何属性的类型。它的行为就好像 implements Bar
不存在一样,推断出 Foo
的所有类型的属性,然后只是 对照 Bar
检查 。例如:
interface Foo {
x: 0 | 1;
}
class Bar implements Foo {
x = 1; // error! x is inferred as number, not 0 | 1
}
这是一个错误,因为 class Bar { x = 1 }
只会为 x
推断出 number
,并且由于 number
不能分配给 0 | 1
,所以这是一个错误.这种行为让很多人感到惊讶和不愉快,并且有很多 GitHub 问题在这里要求更好的东西。请参阅 microsoft/TypeScript#10570 了解一个特别长期未解决的问题。
这意味着 PersonImpl
的 name
属性 是 string
类型,而不是 readonly
:
class PersonImpl implements Greeting {
name: string; // string, not readonly string
//...
}
只读属性可与可变属性相互赋值
第二个问题是,仅在属性 readonly
方面不同的类型被编译器认为是相互兼容的。您可以将 {readonly x: string}
分配给 {x: string}
,反之亦然,不会出错。请参阅
所以这意味着编译器不会发出 PersonImpl
的 name
属性 是可变的而 Greeting
是 readonly
的错误。这些类型不被认为是不兼容的。
把它们放在一起,你就会得到你在这里看到的怪异之处。您可能会愉快地假设 PersonImpl
的 name
属性 是 readonly
,然后当您被允许为其赋值时会感到困惑。
这里的修复是 class 继承的打字问题的一般解决方法;为您的属性提供显式类型注释和修饰符:
class PersonImpl implements Greeting {
readonly name: string; // annotate with readonly
/* ... */
}
let pers = new PersonImpl("maha");
pers.name = "maha2"; // error