![](/img/trans.png)
[英]How to define a nonserializable property for TypeScript `class` or `interface`?
[英]How to define an interface as a class property?
当从 class 继承时,您必须使用 super 属性将所需的 arguments 传递给父 class 的构造函数方法,因此,您必须记住哪些是必填字段,因此您必须记住以下示例:
class Person {
constructor(name: string, age: number) {
// ...
}
}
class Boy extends Person {
constructor(name: string, age: number) { //see, I have to remember property & type
super(name, age);
}
}
所以,我在想一种方法,其中一个解决方案是从使用位置 arguments更改为命名 arguments ,因此您可以使用构建器模式来实现这一点,然后您将使用接口,然后您将在child和parent之间共享该接口,因此:
interface PersonProps {
name: string;
age: number;
}
class Person {
constructor(props: PersonProps) {
// props.name ...... props.age
}
}
class Boy extends Person {
constructor(personSuper: PersonProps) {
super(personSuper);
}
}
现在这种方法的问题是我们打破了内聚规则,这意味着所有相关的代码都应该在一个独立的单元中 go 。
So, to write a better code, -of course- you'll split these files into multiple files, so the Person class should go to a separate file, and the Boy class should go to a separate file, but the problem is that each这两个文件中的一个取决于PersonProps 接口,在我看来,为该接口创建一个单独的文件不是一个好主意,因为 Person class 和该接口高度相关,所以我要做的是让PersonProps 接口与Person class 一起存在于一个文件中。
所以现在是文件树:
.
├── Boy.js
├── Boy.ts
├── Person.js
├── Person.ts
└── tsconfig.json
现在, Person class完成了,现在问题出在Boy class 上,因为它还依赖于PersonProps 接口。
所以你可能会想我会从Person.ts 模块中导出PersonProps 接口,其实我不会,主要是因为你可能在一个文件中有多个class,例如Person.ts 文件可能稍后包含多个 class,并且并非所有这些类都会有接口,因此,我们将打破这种模式,慢慢地代码会变成垃圾,因此,我正在寻找的是将该接口包含在Person class,那么该 Person class 的所有实例都将继承实例内的 PersonProps 接口。
说了很多,下面是两个文件现在的样子:
人.ts:
interface PersonProps {
name: string;
age: number;
}
class Person {
constructor(props: PersonProps) {
// props.name ...... props.age
}
}
男孩.ts:
import { Person } from "./Person";
class Boy extends Person {
constructor(personSuper: PersonProps) {
super(personSuper);
}
}
现在我们需要将 Boy.ts 与PersonProps接口连接起来,其中一个人会说“嘿,就在前面 go 并从 Person.ts 导出接口,导出接口 PersonProps ...”该解决方案可能有效,但是,不,正如我所提到的,这将打破这种模式。 并且代码会慢慢开始发出很大的噪音。
在这里,我们将得出 2 个很好的解决方案:
[第一的]:
在 Person.ts 中,从 Person class 旁边删除 export 关键字,然后在文件末尾写下:
export = {
Person: {
Person,
PersonProps, // ERROR!
},
};
由于一个非常未知的逻辑原因,这给出了编译时错误,为什么不允许这样做?
[第二]:
正如我之前提到的,只需让PersonProps成为 class 实例中的属性,因此:
所以完整的文件将如下所示:
人.ts:
interface PersonProps {
name: string;
age: number;
}
class Person {
PersonProps: interface; // ERROR!
constructor(props: PersonProps) {
// props.name ...... props.age
this.PersonProps = PersonProps; // ERROR!
}
}
这里有两个编译时错误:
现在,最后,在写了这个很长的问题之后:
你的问题很常见:
类只能将值作为属性,而不是类型。 别担心,有一种方法,TypeScript 中的命名空间也可以有类型,并且可以与任何值(类,function. 或变量)具有相同的名称:代码如下所示:
class Person {
constructor(props: Person.Props) {
// ...
}
}
namespace Person {
export interface Props {
name: string;
age: number;
}
}
但请记住,这不是 class 属性,因此您不能使用this.Props
或this['Props']
。
如果您使用普通的 TypeScript 编译器,请使用ECMAScript模块。 TypeScript 自动编译为 Node.js 模块。 您在导入中使用了它,但在导出中没有使用它。 不要使用export = {}
。 有关更多信息,请参阅TypeScript 文档。
在 tsconfig.json 中:
{
"compilerOptions": {
// ...
"moduleResolution": "node",
"module": "commonjs"
}
}
接着:
export class Person {
constructor(props: Person.Props) {
//...
}
}
export namespace Person {
export interface Props {
name: string;
age: number;
}
}
import {Person} from "./Person";
export class Boy extends Person {
constructor(props: Person.Props) {
super(props);
}
}
如果您不知道为什么export
在命名空间中,那么没有export
的命名空间中的属性是私有的(您只能在命名空间TypeScript 文档中访问它以获取更多信息。另外,将属性props
命名为不一样界面。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.