نحن نستخدم TypeScript لأنه يجعل التطوير أكثر أمانًا وسرعة.
لكن في رأيي ، يحتوي TypeScript على الكثير من الانغماس خارج الصندوق. إنها تساعد في توفير القليل من الوقت لمطوري JavaScript عند التبديل إلى TS ، ولكنها تستهلك الكثير من الوقت على المدى الطويل.
لقد قمت بتجميع مجموعة من الإعدادات والإرشادات لاستخدام أكثر صرامة لـ TypeScript. عليك أن تعتاد عليهم مرة واحدة - وسيوفرون الكثير من الوقت في المستقبل.
أي
أبسط قاعدة تمنح فريقي الكثير من الأرباح على المدى الطويل:
لا تستخدم أي.
لا توجد مواقف عمليًا لا يمكنك فيها وصف نوع بدلاً من استخدام أي منها. إذا وجدت نفسي في موقف حيث يتعين علي كتابة أي مشروع طويل الأجل ، فعادة ما أجد مشاكل في الهندسة المعمارية أو الكود القديم.
استخدم الأنواع العامة أو غير المعروفة أو الأحمال الزائدة ويمكنك نسيان أخطاء البيانات غير المتوقعة. يصعب أحيانًا التعرف على مثل هذه المشكلات وتصحيحها مكلف للغاية.
, any, — № 3.
strict
TypeScript strict-, , , . TypeScript. , .
strict- undefined is not a function cannot read property X of null. .
-?
, strict .
strict- , . , . , , , .
, — . strict- . . . , . strict-!
, . , @ts-ignore TODO. .
// tsconfig.json file
{
// ...,
"compilerOptions": {
// a set of cool rules
"noImplicitAny": true,
"noImplicitThis": true,
"strictNullChecks": true,
"strictPropertyInitialization": true,
"strictBindCallApply": true,
"strictFunctionTypes": true,
// a shortcut enabling 6 rules above
"strict": true,
// ...
}
}readonly
— readonly.
, , — . , Angular- : , .
? readonly .
?
, , , readonly-.
readonly :
// before
export interface Thing {
data: string;
}
// after
export interface Thing {
readonly data: string;
}readonly :
// Before
export type UnsafeType = { prop: number };
// After
export type SafeType = Readonly<{ prop: number }>;readonly , :
// Before
class UnsafeComponent {
loaderShow$ = new BehaviorSubject<boolean>(true);
}
// After
class SafeComponent {
readonly loaderShow$ = new BehaviorSubject<boolean>(true);
}readonly-:
// Before
const unsafeArray: Array<number> = [1, 2, 3];
const unsafeArrayOtherWay: number[] = [1, 2, 3];
// After
const safeArray: ReadonlyArray<number> = [1, 2, 3];
const safeArrayOtherWay: readonly number[] = [1, 2, 3];
// three levels
const unsafeArray: number[] = [1, 2, 3]; // bad
const safeArray: readonly number[] = [1, 2, 3]; // good
const verySafeTuple: [number, number, number] = [1, 2, 3]; // super
const verySafeTuple: readonly [number, number, number] = [1, 2, 3]; // awesome (after v3.4)
// Map:
// Before
const unsafeMap: Map<string, number> = new Map<string, number>();
// After
const safeMap: ReadonlyMap<string, number> = new Map<string, number>();
// Set:
// Before
const unsafeSet: Set<number> = new Set<number>();
// After
const safeSet: ReadonlySet<number> = new Set<number>();as const
TypeScript v3.4 const-assertions. , readonly-, . : .
, as const IDE .
Utility Types
TypeScript , .
TypeScript . , .
. , :
( repl.it)
import {Subject} from 'rxjs';
import {filter} from 'rxjs/operators';
interface Data {
readonly greeting: string;
}
const data$$ = new Subject<Data | null>();
/**
* source$ "Observable<Data | null>"
* "null" filter
*
* , TS , .
* "value => !!value" boolean,
*/
const source$ = data$$.pipe(
filter(value => !!value)
)
/**
*
*
* , value Data.
* , "wellTypedSource$"
*/
const wellTypedSource$ = data$$.pipe(
filter((value): value is Data => !!value)
)
// , :)
// source$.subscribe(x => console.log(x.greeting));
wellTypedSource$.subscribe(x => console.log(x.greeting));
data$$.next({ greeting: 'Hi!' });:
typeof — JavaScript .
instanceof — JavaScript .
is T — TypeScript, . , TS’ .
:
( repl.it)
// typeof narrowing
function getCheckboxState(value: boolean | null): string {
if (typeof value === 'boolean') {
// value has "boolean" only type
return value ? 'checked' : 'not checked';
}
/**
* value “null”
*/
return 'indeterminate';
}
// instanceof narrowing
abstract class AbstractButton {
click(): void { }
}
class Button extends AbstractButton {
click(): void { }
}
class IconButton extends AbstractButton {
icon = 'src/icon';
click(): void { }
}
function getButtonIcon(button: AbstractButton): string | null {
/**
* "instanceof" TS , "icon"
*/
return button instanceof IconButton ? button.icon : null;
}
// is T narrowing
interface User {
readonly id: string;
readonly name: string;
}
function isUser(candidate: unknown): candidate is User {
return (
typeof candidate === "object" &&
typeof candidate.id === "string" &&
typeof candidate.name === "string"
);
}
const someData = { id: '42', name: 'John' };
if (isUser(someData)) {
/**
* TS , someData User
*/
console.log(someData.id, someData.name)
}, , , . , TypeScript, , , , . .