- علم صارم يتضمن الأعلام التالية:
--strictNullChecks--alwaysStrict--noImplicitAny--noImplicitThis--strictBindCallApply--strictFunctionTypes--strictPropertyInitializationنعطي أمثلة ونحاول أن نفهم في مكان واحد ما يعنيه كل هذا.// I. - strictNullChecks
المشكلة الشهيرة مع NPE (استثناء مؤشر فارغ ، خطأ مليار دولار) في سياق TS.بشكل افتراضي ، في جميع أنواع TS تكون خالية (Nullable) وهذا يعني أنه يمكننا تمرير | "غير محدد" | "Null" حيث يُتوقع أي نوع آخر (حتى بدائي):const bar1: { foo: number } = undefined;
const bar2: { foo: number } = null;
const bar3: number = null;
const bar4: string = null;
الأمثلة الأكثر إثارة للاهتمام هي استدعاء الأسلوب ، والذي قد لا يكونdeclare var smth: { optionalMethod?(): string; };
smth.optionalMethod();
من الواضح أيضًا أنه لا يمكننا إرجاع "غير محدد" | "Null" حيث من غير الواضح أن هذا متوقعfunction getIt(): { data: number } {
return undefined;
}
getIt().data;
سيتعين علينا الإشارة صراحةً إلى أن كلمة "غير محددة" يمكن أن تعود ، وبعد ذلك فقط نتلقى خطأًfunction getIt(): { data: number } | undefined {
return undefined;
}
getIt().data;
وكمكافأة - عمليات أكثر أمانًا ، حيث قد لا تكون هناك نتيجة ، سيكون هناك خطأ في تشغيل العلم وسيكون عليك التحقق صراحة من أن "العثور" على شيء ما وجد:
[{ name: 'John', age: 4 }]
.find(el => el.age === 42)
.name;
// الثاني. - دائما صارم
لإضافة تعليق توضيحي "استخدام صارم" لكل ملف ، مما يجعل سلوك JS أكثر وضوحًا// III. - لا ضمني
يحظر الاستخدام الضمني لـ "أي" في TS ، أي كود بدون تعليق توضيحي
function id(arg) {
return arg;
}
إنه يساعد كثيرًا في الاستيراد بدون نمط من مكتبات الجهات الخارجية ، حيث يعرض تثبيت تعريفات الأنواع
import * as session from '3rd-party-lib';
// IV. --التصحيحالتصحيحالتطبيق
ويتضمن فحصًا من النوع "أكثر صرامة" لـ "bind" / "call" / "تنطبق" ، بدون إشارة - كل هذا عبارة عن TS صالح. function getFullName(name: string, surname: string): string {
return name + surname;
}
getFullName.call(null, 'John', 42);
getFullName.apply(null, ['John', 42]);
getFullName.bind(null)('John');
getFullName.bind(null, 'John')();
getFullName.bind(null, 'John')(42);
// V. --strictPropertyInitialization + --strictNullChecks
يساعد على تتبع أن جميع الخصائص تمت تهيئتها في المُنشئ ؛ يجب أيضًا تمكين --strictNullChecks لتعطيل أنواع Nullable. class User {
name: string;
}
ومع ذلك ، إذا لم تكن المهمة في المنشئ نفسه ، أقنع TS بأن كل شيء على ما يرام. class User2 {
name: string;
constructor(name: string) {
this.initializeName();
}
initializeName() {
this.name = 'John'
}
}
إذا لم تتمكن من إقناع TS بأن الملكية ستتم تهيئتها تمامًا ، يمكنك أن تقول "أقسم بأمي ، سأقوم بالتأكيد بالتهيئة!" أو باختصار "!"class User3 {
name!: string;
}
// السادس. - أنواع الوظائف الصارمة
إزالة التحقق من المتغيرات للبحث عن الحجج.باختصار ، المتغير في البرمجة - هذه هي القدرة على تمرير Supertype / Subtype هناك ، حيث يكون النوع متوقعًا. على سبيل المثال ، هناك شكل هرمي -> دائرة -> مستطيل ، هل من الممكن نقل أو إرجاع شكل / مستطيل إذا كان من المتوقع أن تكون الدائرة ؟برمجة خيار ، SOinterface Shape { name: string };
interface Circle extends Shape { width: number };
interface Rectangle extends Circle { height: number };
declare var logSC: (figure: Shape) => Circle;
declare var logRC: (figure: Rectangle) => Circle;
declare var logCC: (figure: Circle) => Circle;
declare var logCS: (figure: Circle) => Shape;
declare var logCR: (figure: Circle) => Rectangle;
declare var wlogBB: (fn: (figure: Circle) => Circle) => void;
wlogBB(logCC);
wlogBB(logSC);
wlogBB(logCR);
wlogBB(logCS);
wlogBB(logRC);
من المفهوم أن الدالة لا يجب أن تحور الوسيطة التي تم تمريرها (تعمل كمنتج نوع) ، لا توجد أخطاء في TS ، في الواقع - هناكconst squares: Square[] = [{ name: 'Square', width: 5 }];
function addSmth(arg: Shape[]) {
arg.push({ name: 'Square' });
}
addSmth(squares);
// السابع. - لا شيء ضمني
إذا تم تحديد الوظيفة خارج الكائن / الفئة ، فسوف يطلب منك TS الإشارة صراحةً إلى ما سيشير إليه "هذا" باستخدام أول وسيطة زائفة تسمى "هذا"
function getName(this: { name: string }, surname: string): string {
return this.name;
}
getName.call({}, 'Smith');
getName.apply({}, ['Smith']);
getName.bind({})('Smith');
ستكون المكالمات صالحةconst somePerson = { name: 'John', getName };
const fullName: string = somePerson.getName('Smith')
getName.call({name: 'John'}, 'Smith');
getName.apply({name: 'John'}, ['Smith']);
getName.bind({name: 'John'})('Smith');
يمكن أن تتسبب وظائف المُنشئ في حدوث مشكلاتfunction Person(this: { name: string }, name: string) {
this.name = name;
}
const person = new Person('John');
مكافأة مثيرة للاهتمام هي إضافة مقارنة بين طرق ربط السياق للفئات.class A {
x = 42;
constructor() {
this.getBound = this.getBound.bind(this);
}
getSimple(): number {
return this.x;
}
getSimpleAnnotated(this: A): number {
return this.x;
}
getArrow = (): number => this.x;
getBound(this: A): number {
return this.x;
}
}
const a = new A();
const getSimple = a.getSimple;
getSimple();
const getSimpleAnnotated = a.getSimpleAnnotated;
getSimpleAnnotated();
const getArrow = a.getArrow;
getArrow();
const getBound = a.getBound;
getBound();