رأى كل مطور Angular ديكور في رمز الرمز الزمني. يتم استخدامها لوصف الوحدات النمطية ، وتكوين حقن التبعية ، أو تكوين مكون. بمعنى آخر ، يتم استخدام الديكور لوصف معلومات إضافية أو بيانات وصفية لإطار أو مترجم (في حالة الزاوي). علاوة على ذلك ، Angular مجرد مثال واحد. هناك العديد من المكتبات الأخرى التي تستخدم الديكور من أجل بساطة وتصور الشفرة ، كنهج تعريفي. كمطور .NET في الماضي ، أرى الكثير من أوجه التشابه بين الديكور TS وسمات .NET. وأخيرًا ، فإن إطار تطبيق الواجهة الخلفية NestJS المتنامي (تجريد عبر العقدة) مبني أيضًا على الاستخدام المكثف للديكور والنهج الإعلاني. كيف يعمل كل شيء وكيفية استخدام الديكور في التعليمات البرمجية الخاصة بك ،لجعله أكثر ملاءمة وقراءة؟ ندرك جميعًا أنه بعد تجميع كود TS ، نحصل على كود Javascript. حيث لا يوجد مفهوم للديكور ، مثل العديد من ميزات Typescript الأخرى. لذلك ، بالنسبة لي ، فإن السؤال الأكثر إثارة للاهتمام هو ما الذي يتحول إليه الديكور بعد التجميع. لمتابعة هذه المسألة ، ألقيت كلمة في اجتماع في مينسك وأريد مشاركة المقالة.

. , .
@NgModule({
imports: [
CommonModule,
],
exports: [
],
})
export class NbThemeModule {}
- for component declaration
@Component({
selector: 'nb-card-header',
template: `<ng-content></ng-content>`,
})
export class NbCardHeaderComponent {}
, , , .
, tsconfig.json
, emitDecoratorMetadata
experimentalDecorators
, .
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"target": "es2017",
},
}
, — , , , get , . @expression
, @
. expression
. , , .
, — , , . - .
, — . , -, ( ). , , .
— . Typescript :
declare type MethodDecorator =
<T>(
target: Object,
propertyKey: string | symbol,
descriptor: TypedPropertyDescriptor<T>)
=> TypedPropertyDescriptor<T> | void;
, . :
:
interface TypedPropertyDescriptor<T> {
enumerable?: boolean;
configurable?: boolean;
writable?: boolean;
value?: T;
get?: () => T;
set?: (value: T) => void;
}
, , .
, - , . Javascript .
, - . — .
class TestServiceDeco {
@LogTime()
testLogging() {
...
}
}
, . Typescript , . , - , .
:
function LogTime() {
return (target: Object, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) => {
const method = descriptor.value;
descriptor.value = function(...args) {
console.time(propertyName || 'LogTime');
const result = method.apply(this, args);
console.timeEnd(propertyName || 'LogTime');
return result;
};
};
}
, — , . — target, propertyName . .
— , . , , . .
Javascript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function LogTime() {
return (target, propertyName, descriptor) => {
const method = descriptor.value;
descriptor.value = function (...args) {
console.time(propertyName || 'LogTime');
const result = method.apply(this, args);
console.timeEnd(propertyName || 'LogTime');
return result;
};
};
}
exports.LogTime = LogTime;
, Typescript . :
Object.defineProperty(exports, "__esModule", { value: true });
const log_time_decorator_1 = require("../src/samples/log-time.decorator");
class TestServiceDeco {
testLogging() {
... }
}
__decorate([
log_time_decorator_1.LogTime(),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", void 0)
], TestServiceDeco.prototype, "testLogging", null);
__decorate
, .
, target
prototype
, .
, __decorate
, , . , . .
, . — . — . — Dependency Injection. . , :
@CustomBehavior({
singleton: false,
})
class TestServiceDeco {
constructor() {
console.log('TestServiceDeco ctor');
}
}
, Typescript:
declare type ClassDecorator =
<TFunction extends Function>(target: TFunction)
=> TFunction | void;
:
import 'reflect-metadata';
interface Metadata {
singleton?: boolean;
}
function CustomBehavior(metadata: Metadata) {
return function(ctor: Function) {
Reflect.defineMetadata('metadataKey', metadata, ctor);
}
}
. — singelton- . .
:
Reflect-metadata Typescript. , — . , , .
import 'reflect-metadata';
const instancesMap: Map<Object, Object> = new Map<Object, Object>();
function getInstance<T>(tType: new () => T): T {
let metadata = Reflect.getMetadata('metadataKey', tType) as Metadata;
if (metadata.singleton) {
if (!instancesMap.has(tType)) {
instancesMap.set(tType, new tType());
}
return instancesMap.get(tType) as T;
} else {
return new tType() as T;
}
}
getInstance
, , ,Reflect.getMetadata
, . any
, as Metadata
- , .
tType: new () => T
- - , Map
, , .
getInstance
, .
, . , Javascript .
. , , , . , Person
Age
, 18 60. :
class Person {
@Age(18, 60)
age: number;
}
:
declare type PropertyDecorator =
(target: Object, propertyKey: string | symbol) => void;
:
import 'reflect-metadata';
function Age(from: number, to: number) {
return function (object: Object, propertyName: string) {
const metadata = {
propertyName: propertyName,
range: { from, to },
};
Reflect.defineMetadata(`validationMetadata_${propertyName}`, metadata, object.constructor);
};
}
, . . , , , . , .
:
class Person {
...
}
__decorate([
age_decorator_1.Age(18, 60),
__metadata("design:type", Number)
], Person.prototype, "age", void 0);
, __decorate
, .
, — , . — , , .
, :
function validate<T>(object: T) {
const properties = Object.getOwnPropertyNames(object);
properties.forEach(propertyName => {
let metadata = Reflect.getMetadata(metaKey + propertyName, object.constructor);
if (metadata && metadata.range) {
const value = object[metadata.propertyName];
if (value < metadata.range.from || value > metadata.range.to) {
throw new Error('Validation failed');
}
}
});
}
, , . .
:
const person = new Person();
person.age = 40;
validate(person);
person.age = 16;
validate(person);
, , , .
, :
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
Class-Validator
Class-Validator, . .
export class Post {
@Length(10, 20)
title: string;
@IsInt()
@Min(0)
@Max(10)
rating: number;
@IsEmail()
email: string;
}
...
validate(object).then(errors => {
if (errors.length > 0) {
console.log("validation failed. errors: ", errors);
} else {
console.log("validation succeed");
}
});
, . .
, NestJS @UsePipes(new ValidationPipe())
http .
Typescript , . , -. , , , , , , , … Angular NestJS. ( ).
, , , , , !
ملاحظة أثناء الكتابة (أو بالأحرى ترجمة مقالته) ، وجدت واحدة أخرى هناك على المحور ، والتي تكشف جيدًا عن موضوع الديكور. أعطي رابط