Загрузка…
Загрузка…
TypeScript · senior · сложность 9
Система типов TypeScript — Turing-complete чистый функциональный язык на compile time: conditional — if, mapped — for, рекурсия — цикл, infer — pattern-match. Это мощно — и каждый хитрый тип вы платите на каждом нажатии клавиши в редакторе.
Два уровня: value-level JS и type-level «программа», которая никогда не бежит в runtime. Из кубиков (extends ? :, [K in …], infer, recursive aliases) собирают парсеры строк, deep readonly, вычисление ключей API.
Цена: сложность, время typecheck, нечитаемые ошибки. Сеньор знает не только как, но и когда остановиться — часто хватит простого union/generic.
type NonNull<T> = T extends null | undefined ? never : T;
type A = NonNull<string | null>; // string ← ran per-member, never dropped outtype IsNever<T> = [T] extends [never] ? true : false; // [ ] disables distributiontype Mutable<T> = { -readonly [K in keyof T]: T[K] }; // strip readonly
type Getters<T> = { [K in keyof T & string as `get${Capitalize<K>}`]: () => T[K] };type ElementOf<T> = T extends readonly (infer E)[] ? E : never;
type Un = ElementOf<number[]>; // number// Split a route string into its segments — string parsing at the type level
type Split<S extends string> =
S extends `${infer Head}/${infer Tail}` ? [Head, ...Split<Tail>] : [S];
type R = Split<'users/:id/posts'>; // ['users', ':id', 'posts']// A recursive DeepReadonly — mapped + conditional + recursion together
type DeepReadonly<T> = T extends (infer E)[]
? ReadonlyArray<DeepReadonly<E>>
: T extends object
? { readonly [K in keyof T]: DeepReadonly<T[K]> }
: T; // primitives bottom out the recursion
type Config = { db: { host: string; ports: number[] } };
type Frozen = DeepReadonly<Config>;
// { readonly db: { readonly host: string; readonly ports: readonly number[] } }// Template-literal + infer as a typed string parser (real use: typed i18n keys)
type Params<S extends string> =
S extends `${string}:${infer P}/${infer Rest}` ? P | Params<Rest>
: S extends `${string}:${infer P}` ? P
: never;
type P = Params<'/users/:userId/posts/:postId'>; // 'userId' | 'postId'Type-level programming — мощный compile-time DSL; применяйте для библиотек и сложных контрактов, не для каждого CRUD-поля.