Typescript 自定义接口变量声明
Typescript custom interface variable declaration
这里是 TypeScript 新手,我目前正在 TutorialsPoint here 上学习这门语言。
我目前很难理解这两段代码之间的区别。
interface Person{
age: number;
}
interface Musician extends Person{
instrument: string;
}
var drummer:Musician = {
instrument: "drum",
age: 28
}
和
interface Person{
age: number;
}
interface Musician extends Person{
instrument: string;
}
var drummer = <Musician>{}
drummer.instrument = "drum"
drummer.age = 28
两者有什么区别?是否存在使用 first/second 实现更好的特定情况?
谢谢。
示例略有不同:
- 首先,您要定义类型为
Musician
的变量,然后将对象分配给适合该类型的变量。
- 第二,你定义了一个没有显式类型的变量(这意味着 TypeScript 会推断它),创建一个空对象,然后 casting 该对象以键入
Musicican
。
- 顺便说一句,在 TypeScript 中进行转换的首选语法是
{} as Musician
- 您使用的尖括号语法与 React 应用程序常用的 JSX 语法扩展不兼容,因此它被替换了有一些不那么模棱两可的东西。
在绝大多数情况下,我会推荐第一个示例而不是第二个示例 - 空对象并没有真正实现 Musician
,因此您实际上是在回避类型检查器!
您可以使用第二种方法的一种情况是,如果您有一个 Musician
一开始是空的,后来又被填充了——不过在那种情况下,我认为您会通过将字段设为可选,通过类型定义本身进行建模会更好:
interface Person {
// '?' makes a field optional
age?: number;
}
interface Musician extends Person {
instrument?: string;
}
// The cast can now be replaced with a proper type
var drummer: Musician = {};
drummer.instrument = "drum";
drummer.age = 28;
这让(您、其他开发人员和编译器)更清楚地知道在某些情况下这些字段将是未定义的。
它们最终是一样的,但在可能的情况下首选前者。
在这种情况下:
var drummer: Musician = {
instrument: "drum",
age: 28
}
您通过使用 type annotation 并为其分配对象文字来声明 drummer
是 Musician
。编译器对此很满意,因为它可以验证是的,您分配的对象文字与 Musician
接口兼容。它有一个字符串值 instrument
属性 和一个数值 age
属性。
现在如果我们尝试这个会怎样:
var drummer: Musician = {};
// ~~~~~~~ <-- error!
// Type '{}' is not assignable to type 'Musician'.
// Property 'instrument' is missing in type '{}'.
drummer.instrument = "drum"
drummer.age = 28
将空对象文字赋值给声明为 Musician
的值会导致编译器错误。毕竟,空对象字面量没有字符串值 instrument
属性 或数值 age
属性。你被警告了。现在,您 知道接下来的两行将解决该问题,但编译器不会。
因此您可以将其更改为使用 type assertion 而不是类型注释:
var drummer = <Musician>{}; // okay
drummer.instrument = "drum"
drummer.age = 28
断言是您告诉编译器的地方 "this object is really a Musician
, even though right now it doesn't look like it." 您负责确保 drummer
是 Musician
并减轻编译器验证的责任给你。
并且由于接下来的两行添加了所需的属性,所以一切都很好。
前者更可取,因为您通常希望编译器在可能的情况下验证您的类型。类型断言放弃了一些安全性,这很好,直到它不是,就像驾驶没有安全带的汽车:
var drummer = <Musician>{}; // okay
drummer.age = 28;
// whoops, forgot the instrument, but TypeScript isn't complaining
// ... later ...
console.log(drummer.instrument.toUpperCase());
// no error at compile time
// but blows up at runtime
有时您必须使用类型断言。例如,当您有某种循环引用需要分段构建对象时:
interface MarriedPerson extends Person {
spouse: MarriedPerson
}
var adam: MarriedPerson = {
age: 0,
// spouse: eve <-- can't do this before eve is defined
} as MarriedPerson;
var eve: MarriedPerson = {
age: 0,
spouse: adam
}
adam.spouse = eve; // okay now
在上面,每个 MarriedPerson
都需要对 MarriedPerson
... 的引用,但是在您创建一个之前不会有一个。因此,您不得不求助于 MarriedPerson
对象之一没有所需 spouse
的短时间。因此需要断言。
这有意义吗?希望能帮助到你;祝你好运!
这里是 TypeScript 新手,我目前正在 TutorialsPoint here 上学习这门语言。 我目前很难理解这两段代码之间的区别。
interface Person{
age: number;
}
interface Musician extends Person{
instrument: string;
}
var drummer:Musician = {
instrument: "drum",
age: 28
}
和
interface Person{
age: number;
}
interface Musician extends Person{
instrument: string;
}
var drummer = <Musician>{}
drummer.instrument = "drum"
drummer.age = 28
两者有什么区别?是否存在使用 first/second 实现更好的特定情况?
谢谢。
示例略有不同:
- 首先,您要定义类型为
Musician
的变量,然后将对象分配给适合该类型的变量。 - 第二,你定义了一个没有显式类型的变量(这意味着 TypeScript 会推断它),创建一个空对象,然后 casting 该对象以键入
Musicican
。- 顺便说一句,在 TypeScript 中进行转换的首选语法是
{} as Musician
- 您使用的尖括号语法与 React 应用程序常用的 JSX 语法扩展不兼容,因此它被替换了有一些不那么模棱两可的东西。
- 顺便说一句,在 TypeScript 中进行转换的首选语法是
在绝大多数情况下,我会推荐第一个示例而不是第二个示例 - 空对象并没有真正实现 Musician
,因此您实际上是在回避类型检查器!
您可以使用第二种方法的一种情况是,如果您有一个 Musician
一开始是空的,后来又被填充了——不过在那种情况下,我认为您会通过将字段设为可选,通过类型定义本身进行建模会更好:
interface Person {
// '?' makes a field optional
age?: number;
}
interface Musician extends Person {
instrument?: string;
}
// The cast can now be replaced with a proper type
var drummer: Musician = {};
drummer.instrument = "drum";
drummer.age = 28;
这让(您、其他开发人员和编译器)更清楚地知道在某些情况下这些字段将是未定义的。
它们最终是一样的,但在可能的情况下首选前者。
在这种情况下:
var drummer: Musician = {
instrument: "drum",
age: 28
}
您通过使用 type annotation 并为其分配对象文字来声明 drummer
是 Musician
。编译器对此很满意,因为它可以验证是的,您分配的对象文字与 Musician
接口兼容。它有一个字符串值 instrument
属性 和一个数值 age
属性。
现在如果我们尝试这个会怎样:
var drummer: Musician = {};
// ~~~~~~~ <-- error!
// Type '{}' is not assignable to type 'Musician'.
// Property 'instrument' is missing in type '{}'.
drummer.instrument = "drum"
drummer.age = 28
将空对象文字赋值给声明为 Musician
的值会导致编译器错误。毕竟,空对象字面量没有字符串值 instrument
属性 或数值 age
属性。你被警告了。现在,您 知道接下来的两行将解决该问题,但编译器不会。
因此您可以将其更改为使用 type assertion 而不是类型注释:
var drummer = <Musician>{}; // okay
drummer.instrument = "drum"
drummer.age = 28
断言是您告诉编译器的地方 "this object is really a Musician
, even though right now it doesn't look like it." 您负责确保 drummer
是 Musician
并减轻编译器验证的责任给你。
并且由于接下来的两行添加了所需的属性,所以一切都很好。
前者更可取,因为您通常希望编译器在可能的情况下验证您的类型。类型断言放弃了一些安全性,这很好,直到它不是,就像驾驶没有安全带的汽车:
var drummer = <Musician>{}; // okay
drummer.age = 28;
// whoops, forgot the instrument, but TypeScript isn't complaining
// ... later ...
console.log(drummer.instrument.toUpperCase());
// no error at compile time
// but blows up at runtime
有时您必须使用类型断言。例如,当您有某种循环引用需要分段构建对象时:
interface MarriedPerson extends Person {
spouse: MarriedPerson
}
var adam: MarriedPerson = {
age: 0,
// spouse: eve <-- can't do this before eve is defined
} as MarriedPerson;
var eve: MarriedPerson = {
age: 0,
spouse: adam
}
adam.spouse = eve; // okay now
在上面,每个 MarriedPerson
都需要对 MarriedPerson
... 的引用,但是在您创建一个之前不会有一个。因此,您不得不求助于 MarriedPerson
对象之一没有所需 spouse
的短时间。因此需要断言。
这有意义吗?希望能帮助到你;祝你好运!