打字稿库如何在运行时设法读取类型
How do typescript libraries manage to read types at runtime
当源代码从 typescript 编译为 javascript 时,类型注释被剥离,并且无法在运行时检查变量的类型。
但是,有许多打字稿库似乎会根据 class 属性的类型注释更改行为。例如,在编写 typeorm 实体时,我们可以这样写:
@Entity()
class MyEntity extends BaseEntity {
@Field()
public id: number // automatically infers int database type
@Field()
public description: string // automatically infers varchar or text database type
@Field()
public image: string | null // cannot infer correct type, will throw error
}
我们也有与 typedi(通过构造函数传递正确的引用)、type-graphql(使用正确的 graphql 类型构建 graphql 模式)等类似的东西。当你必须通过装饰器或类似的东西传递函数时,我明白了,但是这些库如何仅从类型注释推断类型?
我很好奇,在 TypeORM 文档中找到了答案 here:
TypeScript configuration
Also, make sure you are using TypeScript version 4.5 or higher, and you have enabled the following settings in tsconfig.json
:
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
我怀疑是告诉 TypeScript 向装饰器提供运行时类型信息,事实上,it does:
Emit Decorator Metadata
emitDecoratorMetadata
Enables experimental support for emitting type metadata for decorators which works with the module reflect-metadata
.
启用后,TypeScript 会在运行时发出对包含类型信息的装饰器的调用。文档中的示例适用于此代码:
class Demo {
@LogMethod
public foo(bar: number) {
// do nothing
}
}
...发出 __decorate
和 __metadata
函数,然后是:
class Demo {
foo(bar) {
// do nothing
}
}
__decorate([
LogMethod,
__metadata("design:type", Function),
__metadata("design:paramtypes", [Number]),
__metadata("design:returntype", void 0)
], Demo.prototype, "foo", null);
如果我们查看您的示例,这就是它为装饰器调用发出的内容:
__decorate([
Field(),
__metadata("design:type", Number)
], MyEntity.prototype, "id", void 0);
__decorate([
Field(),
__metadata("design:type", String)
], MyEntity.prototype, "description", void 0);
__decorate([
Field(),
__metadata("design:type", Object)
], MyEntity.prototype, "image", void 0);
MyEntity = __decorate([
Entity()
], MyEntity);
当源代码从 typescript 编译为 javascript 时,类型注释被剥离,并且无法在运行时检查变量的类型。
但是,有许多打字稿库似乎会根据 class 属性的类型注释更改行为。例如,在编写 typeorm 实体时,我们可以这样写:
@Entity()
class MyEntity extends BaseEntity {
@Field()
public id: number // automatically infers int database type
@Field()
public description: string // automatically infers varchar or text database type
@Field()
public image: string | null // cannot infer correct type, will throw error
}
我们也有与 typedi(通过构造函数传递正确的引用)、type-graphql(使用正确的 graphql 类型构建 graphql 模式)等类似的东西。当你必须通过装饰器或类似的东西传递函数时,我明白了,但是这些库如何仅从类型注释推断类型?
我很好奇,在 TypeORM 文档中找到了答案 here:
TypeScript configuration
Also, make sure you are using TypeScript version 4.5 or higher, and you have enabled the following settings in
tsconfig.json
:"emitDecoratorMetadata": true, "experimentalDecorators": true,
我怀疑是告诉 TypeScript 向装饰器提供运行时类型信息,事实上,it does:
Emit Decorator Metadata
emitDecoratorMetadata
Enables experimental support for emitting type metadata for decorators which works with the module
reflect-metadata
.
启用后,TypeScript 会在运行时发出对包含类型信息的装饰器的调用。文档中的示例适用于此代码:
class Demo { @LogMethod public foo(bar: number) { // do nothing } }
...发出 __decorate
和 __metadata
函数,然后是:
class Demo { foo(bar) { // do nothing } } __decorate([ LogMethod, __metadata("design:type", Function), __metadata("design:paramtypes", [Number]), __metadata("design:returntype", void 0) ], Demo.prototype, "foo", null);
如果我们查看您的示例,这就是它为装饰器调用发出的内容:
__decorate([ Field(), __metadata("design:type", Number) ], MyEntity.prototype, "id", void 0); __decorate([ Field(), __metadata("design:type", String) ], MyEntity.prototype, "description", void 0); __decorate([ Field(), __metadata("design:type", Object) ], MyEntity.prototype, "image", void 0); MyEntity = __decorate([ Entity() ], MyEntity);