TS Everest 004 [Study Notes]

Type manipulation type-1 // Built-in // Partial, Required, Readonly for modifying types // Pick, Omit for manipulating data structures // Exclude, Extract for manipulating union types // Parameters, ReturnType, infer // String types, template literal types `${}` + infer, PartialPropsOptional ...

Type Gymnastics

type-1

// 内置// Partial Required Readonly 修饰类型的// Pick Omit 处理数据结构// Exclude Extract 处理集合类型的// Paramters RetrunValue infer// 字符串类型,模板字符串`${}` + infer

PartialPropsOptional

// 1. Partial
// 2. Optional
// 3. Readonly
// 4. Pick
// 5. Omit

// Partial
// 将对象的属性变为可选的

interface Person {
  name: string;
  age: number;
  address: string;
}

type PartialPropsOptional<T extends Object, K extends keyof T> = Partial<
  Pick<T, K>
> &
  Omit<T, K>;

type Computed<T> = {
  [K in keyof T]: T[K];
};

type p1 = Computed<PartialPropsOptional<Person, 'age' | 'address'>>;

export {};

ExtractKeysByValueType

// 如何通过值类型拿到key
//将类型相同的进映射{name:"name",age:"never",address:"address"}
// name | never | address --> name | address
// 如何判断两个类型是否相同
type isEqual<T, U> = T extends U ? (U extends T ? true : false) : false;

type PickKeysByValue<T, V> = {
  // [K in keyof T]: T[K] extends V ? K : never;
  [K in keyof T]: isEqual<T[K], V> extends true ? K : never;
}[keyof T];

type OmitKeysByValue<T, V> = {
  [K in keyof T]: isEqual<T[K], V> extends true ? never : K;
}[keyof T];

type p2 = Computed<PickKeysByValue<Person, string>>; // 应该拿到name address
type p3 = Computed<OmitKeysByValue<Person, string>>; // 应该拿到age

// 模板字符串,里面有一个很重要的功能,重映射
type PickKeysByValue2<T, U> = {
  // 直接将对象的属性就给忽略掉了
  // 循环对象的key,看值的类型是否相同,如果相同留下这个key
  [K in keyof T as T[K] extends U ? K : never]: T[K];
};

type p4 = PickKeysByValue2<Person, string>;

export {};

OrType.ts

// 子类型互斥 OrType.ts
interface Man1 {
  fortune: string;
}
interface Man2 {
  funny: string;
}
interface Man3 {
  foreign: string;
}

type ManType = Man1 | Man2 | Man3; // 希望ManType只是其中的一种类型
let man: ManType = {
  fortune: '富有',
  funny: '风趣',
  foreign: '洋派',
}; // 希望ManType只是其中的一种类型
// man1-man2 将man1的属性标记成never +man2
// man2-man1 将man2的属性标记成never +man1
type DiscardType<T, U> = {
  [K in Exclude<keyof T, keyof U>]?: never;
};
type OrType<T, U> = (DiscardType<T, U> & U) | (DiscardType<U, T> & T);
type manType2 = OrType<Man3, OrType<Man1, Man2>>;
let man2: manType2 = {
  fortune: '富有',
};

export {};

交 差 并 补

// 对象的 交差并补
type A = {
  name: string;
  age: number;
  address: string;
};

type B = {
  name: string;
  male: boolean;
  address: number;
};

// 交集
type ObjIntersect<T extends object, U extends object> = Pick<
  T,
  Extract<keyof T, keyof U>
>;
type p1 = ObjIntersect<A, B>;

// 差集
type ObjectDiff<T extends object, U extends object> = Pick<
  T,
  Exclude<keyof T, keyof U>
>;
type R2 = ObjectDiff<A, B>;

// 补集 就是差集,要求是有父子关系
type ObjectCom<T extends U, U extends object> = Pick<
  T,
  Exclude<keyof T, keyof U>
>;
// type R3 = ObjectCom<B,A>

// 重写 以后面的类型为准 再加上以前比现在多的类型
type Overwrite<T extends object, U extends object> = ObjIntersect<U, T> &
  ObjectDiff<T, U>;
type Computed<T> = {
  [K in keyof T]: T[K];
} & {};
type R4 = Computed<Overwrite<A, B>>;
export {};

infer

// 模式匹配类型,抢断函数类型中参数的最后一个参数类型
function sum(a: string, b: string, c: number) {}
type LastParam<T extends (...args: any[]) => any> = T extends (
  ...args: infer P
) => any
  ? P extends [...any[], infer L]
    ? L
    : never
  : never;
type X = LastParam<typeof sum>;
export {};

type-2

首字母大写

// 首字母大写
// export type CapitalizeString<T> = T extends string
//   ? `${Capitalize<T & string>}`
//   : T;
// 默认情况,字符串的infer只匹配第一个字符
// 针对字符的infer 默认infer第一个指代的是第一个字符,后面的就是所有的
// 如果有分隔符号,指代的就是分隔符之前的
export type CapitalizeString<T> = T extends `${infer First}${infer Rest}`
  ? `${Capitalize<First>}${Rest}`
  : T;
type a1 = CapitalizeString<'handler'>;
type a2 = CapitalizeString<'parent'>;
type a3 = CapitalizeString<223>;

export {};

FirstChar

// 获取字符串的字面量中的第一个字符
type FirstChar<T extends string> = T extends `${infer L}${infer R}` ? L : T;
type A = FirstChar<'BFE'>; // B
type B = FirstChar<'dev'>; // BFE
type C = FirstChar<'234'>; // 234

LastChar

// lastchar
type LastChar<T, F = never> = T extends `${infer L}${infer R}` ? LastChar<R, L> : F;
type A1 = LastChar<'BFE'>; // E
type B1 = LastChar<'dev'>; // v
type C1 = LastChar<'234'>; // 4

字符串转元组

// string toTuple(元组)
type StringToTuple<T extends string> = T extends `${infer L}${infer R}` ? [L, ...StringToTuple<R>] : [];
type A2 = StringToTuple<'BFE'>; // ['B', 'F', 'E']
type B2 = StringToTuple<'dev'>; // ['d', 'e', 'v']
type C2 = StringToTuple<'234'>; // ['2', '3', '4']

元组转成字符串

// 元组转字符串
type TupleToString<T extends string[]> = T extends [infer L, ...infer R] ? `${L}${TupleToString<R>}` : '';
type A3 = TupleToString<['B', 'F', 'E']>; // 'BFE'
type B3 = TupleToString<['d', 'e', 'v']>; // 'dev'
type C3 = TupleToString<['2', '3', '4']>; // '234'

重复字符串

// repeat string
type RepeatString<
  T extends string,
  C extends number,
  A extends any[],
  F extends string = ''
> = C extends A['length'] ? F : RepeatString<T, C, [...A, any], `${F}${T}`>;
type A4 = RepeatString<'a', 3, [], ''>; // 'aaa'
type B4 = RepeatString<'a', 0, [], ''>; // ''
type C4 = RepeatString<'a', -1, [], ''>; // ''

split string 根据infer的左右分割,在左边放到数组中,右边递归,最终在结果集中增加无法匹配的即可

type SplitString<
  T extends string,
  S extends string,
  A extends any[]
> = T extends `${infer L}${S}${infer R}`
  ? SplitString<R, S, [L, ...A]>
  : [...A, T];
type A5 = SplitString<'handle-open-flag', '-', []>; // ['handle', 'open', 'flag']
type B5 = SplitString<'open-flag', '-', []>; // ['open', 'flag']
type C5 = SplitString<'BFE.dev.fe.js', '.', []>; // ['BFE', 'dev', 'fe', 'js']
type D5 = SplitString<'BFE.dev.fe.js', '-', []>; // ['BFE.dev.fe.js']

计算字符串长度

// 计算字符串字面量的长度
type StringLength<
  T extends string,
  A extends any[]
> = T extends `${infer L}${infer R}` ? StringLength<R, [L, ...A]> : A['length'];
type A6 = StringLength<'BFE.dev', []>; // 7
type B6 = StringLength<'dev', []>; // 3
type C6 = StringLength<'', []>; // 0

驼峰转连接符

// 驼峰命名转横杠命名
// 如何匹配大写? Capitalize<H> extends H
// 把大写变成--> -小写
type RemoveFirstLetter<T extends string> = T extends `-${infer V}` ? V : T;
type KebabCase<
  T extends string,
  F extends string = ''
> = T extends `${infer L}${infer R}`
  ? L extends Capitalize<L>
    ? KebabCase<R, `${F}-${Lowercase<L>}`>
    : KebabCase<R, `${F}${L}`>
  : RemoveFirstLetter<F>;
type aa1 = KebabCase<'HandleOpenFlag'>; // handle-open-flag
type aa2 = KebabCase<'OpenFlag'>; // open-flag

横杠命名转为驼峰命名

// 横杠命名转驼峰命名
type CamelCase<
  T extends string,
  F extends string = ''
> = T extends `${infer L}-${infer R1}${infer R2}`
  ? CamelCase<R2, `${F}${L}${Capitalize<R1>}`>
  : Capitalize<`${F}${T}`>;

type Bb1 = CamelCase<'handle-open-flag', ''>; // HandleOpenFlag
type Bb2 = CamelCase<'open-flag', ''>; // OpenFlag

object-->path

export type ObjectAccessPaths<
  T,
  F extends string = '',
  K = keyof T
> = K extends keyof T
  ? T[K] extends object
    ? // 如果当前的值是对象继续递归拼接,并且将当前解析的key 拼接到结果集中
      ObjectAccessPaths<T[K], `${F}${K & string}.`>
    : `${F}${K & string}` // 这里会丢失不是对象的最后一个key,
  : never;

function createI18n<Schema>(
  schema: Schema
): (path: ObjectAccessPaths<Schema>) => void {
  return (key: string) => {};
}

const i18n = createI18n({
  home: {
    topBar: {
      title: 'Home',
      welcome: '欢迎来到Home',
    },
    bottomBar: {
      notes: '笔记',
    },
  },
  login: {
    title: 'Login',
    username: '用户名',
    password: '密码',
    login: 'Login',
  },
});
i18n('home.topBar.title');
// i18n('home.topBar.title');
i18n('home.bottomBar.notes');
i18n('login.title');
i18n('login.username');
i18n('login.password');
i18n('login.login');
i18n('login.xxx'); // 报错了

判断传入的字符串字面量类型中是否含有某个字符串

// 判断传入的字符串字面量类型中是否含有某个字符串
type Includes<
  T extends string,
  S extends string
> = T extends `${infer L}${S}${infer R}` ? true : false;
type a1 = Includes<'hello', 'h'>; // true
type a2 = Includes<'hello', 'e'>; // true
type a3 = Includes<'hello', 'a'>; // false
type a4 = Includes<'', ''>; //true T extends "" && S extends ""

trim 删除两边的空格

// trim
type TrimLeft<T extends string> = T extends ` ${infer R}` ? TrimLeft<R> : T;
type TrimRight<T extends string> = T extends `${infer R} ` ? TrimRight<R> : T;
type Trim<T extends string> = TrimRight<TrimLeft<T>>;
type a5 = Trim<'  .hello  '>; // '.hello'

replace

// 构建一个查找规则,找到后将左边和右边留起来${infer L}${S}${infer R}

type Replace<
  S extends string,
  From extends string,
  To extends string
> = From extends ''
  ? S
  : S extends `${infer L}${From}${infer R}`
  ? `${L}${To}${Replace<R, From, To>}`
  : S;

type aa1 = Replace<'hello world', 'world', 'walker'>; // 'hello walker'
type bb1 = Replace<'jwjw', 'jw', 'jiangwen'>; // 'jiangwenjiangwen'
type bb2 = Replace<'ha ha ha', 'ha', 'he'>; // 'he he he'
type aa2 = Replace<'jw', 'jw', 'jiangwen'>; // 'jiangwen'
type aa3 = Replace<'a', '', 'jiangwen'>; // 'jiangwenjiangwen'


type Replace1<T extends string,C extends string,RC extends string,F extends string = "">=
C extends ""? T extends ""?RC: `${RC}${T}`:T extends `${infer L}${C}${infer R}`? Replace1<R,C,RC,`${F}${L}${RC}`>:`${F}${T}`
type t1 = Replace1<"ha ha ha","ha","he">
type t2 = Replace1<"jw","jw","jiangwen">
type t3 = Replace1<"a","","jiangwen">
type t4 = Replace1<"","","jiangwen">
// 定义组件的监听事件类型
type EventType = {
  'handle-open': (flage: boolean) => true;
  'preview-item': (data: { item: any; index: number }) => true;
  'close-item': (data: { item: any; index: number }) => true;
};
/*
{
 onHandleOpen: (flage: boolean) => true;
 onPreviewItem: (data: { item: any; index: number }) => true;
 onCloseItem: (data: { item: any; index: number }) => true;
}
*/
// 实现type2
type ComponentEmitsType<T> = {
  [K in keyof T as `on${Capitalize<K>}`]: T[K] extends (...args: infer P) => any?(...args:P)=>void;
};
type EventType2 = ComponentEmitsType<EventType>;
// 转化为类型

Tuple Operations

// 计算元组类型的长度
type LengthOfTuple<T extends any[]> = T extends { length: infer L } ? L : never;
type A = LengthOfTuple<[1, 2, 3, 4, 5]>;
type B = LengthOfTuple<[]>;

// 元组第一项
type FirstItem<T extends any[]> = T extends [infer F, ...infer R] ? F : never;
type C = FirstItem<[1, 2, 3, 4, 5]>;
type D = FirstItem<[]>;

// 元组最后一项
type LastItem<T extends any[]> = T extends [...infer R, infer L] ? L : never;
type E = LastItem<[1, 2, 3, 4, 5]>;

// 移除元组第一项
type RemoveFirstItem<T extends any[]> = T extends [infer F, ...infer R]
  ? R
  : never;
type F = RemoveFirstItem<[1, 2, 3, 4, 5]>;
type G = RemoveFirstItem<[]>;

// 移除元组最后一项
type RemoveLastItem<T extends any[]> = T extends [...infer R, infer L]
  ? R
  : never;
type I = RemoveLastItem<[1, 2, 3, 4, 5]>;
type J = RemoveLastItem<[]>;

// push
type Push<T extends any[], V> = [...T, V];
type H = Push<[1, 2, 3, 4, 5], 6>;

// 反转元组 反转链表
type ReverseTuple<T extends any[]> = T extends [infer F, ...infer R]
  ? [...ReverseTuple<R>, F]
  : T;
type K = ReverseTuple<[1, 2, 3, 4, 5]>;
type L = ReverseTuple<[string, number, boolean]>;
type M = ReverseTuple<[]>;

// flatten 扁平化
type Flatten<T extends any[]> = T extends [infer F, ...infer R]
  ? [...(F extends any[] ? Flatten<F> : [F]), ...Flatten<R>]
  : T;
type N = Flatten<[1, [2, [3, [4, [5]]]]]>;
type O = Flatten<[[1, 2], [3, 4], [5, 6]]>;
type P = Flatten<[1]>;
type Q = Flatten<[]>;

// repeat
type Repeat<T, C extends number, F extends any[] = []> = C extends F['length']
  ? F
  : Repeat<T, C, [...F, T]>;
type A1 = Repeat<number, 3>; //[number,number,number]
type A2 = Repeat<string, 2>; //[string,string]
type A3 = Repeat<boolean, 1>; //[boolean]

// 过滤指定类型
type Filter<T extends any[], U, F extends any[] = []> = T extends [
  infer L,
  ...infer R
]
  ? // 如果需要则放到数组里,不需要返回原来
    Filter<R, U, [L] extends [U] ? [...F, L] : F>
  : F;
type A4 = Filter<[1, 'BEF', 2, true, 'dev'], number>; // [1,2]
type A5 = Filter<[1, 'BEF', 2, true, 'dev'], string>; // ["BEF","dev"]
type A6 = Filter<[1, 'BEF', 2, true, 'dev'], boolean>; // [true]
type A7 = Filter<[1, 'BEF', 2, any, 'dev'], string>; // ["BFE",any,'dev']

// FindIndex
type IsEqual<A, B, Success, Faile> = [A] extends [B]
  ? [B] extends [A]
    ? keyof A extends keyof B
      ? keyof B extends keyof A
        ? Success
        : Faile
      : Faile
    : Faile
  : Faile;
type FindIndex<T extends any[], U, F extends any[] = []> = T extends [
  infer L,
  ...infer R
]
  ? IsEqual<L, U, F['length'], FindIndex<R, U, [...F, L]>>
  : never;

type A8 = [any, never, 1, '2', true];
type A9 = FindIndex<A8, 1>; // 2
type A10 = FindIndex<A8, 3>; // never
type A11 = FindIndex<A8, true>; // 4
type A12 = FindIndex<A8, string>; // never

// 元组转成枚举,枚举对象中的值就是元素中某个元素中某个类型的字面量类型
type a1 = TupleToEnum<['MacOS', 'Windows', 'Linux']>;
// {readonly MacOS: "MacOS"; readonly Windows: "Windows"; readonly Linux: "Linux"}
// 如果传递了第二个参数为true,则枚举对象中值的类型是元素在元组中的index索引
type a2 = TupleToEnum<['MacOS', 'Windows', 'Linux'], true>;
// {readonly MacOS: 0; readonly Windows: 1; readonly Linux: 2}

type TupleToEnum<T extends any[], I extends boolean = false> = {
  readonly [K in T[number]]: IsEqual<I, true, FindIndex<T, K>, K>;
};

// slice
// 如果没有达到开头的长度,就要记录找到了多少个元素
type Slice<
  T extends any[],
  S extends number,
  E extends number = T['length'],
  SA extends any[] = [],
  SE extends any[] = [],
  F extends any[] = []
> = T extends [infer L, ...infer R]
  ? SA['length'] extends S
    ? SE['length'] extends E
      ? [...F, L]
      : Slice<R, S, E, SA, [...SE, null], [...F, L]>
    : Slice<R, S, E, [...SA, null], [...SE, null], F>
  : F;

type S1 = Slice<[any, never, 1, '2', true, boolean], 0, 2>; // [any,never,1]
type S2 = Slice<[any, never, 1, '2', true, boolean], 1, 3>; // [never,1,'2']
type S3 = Slice<[any, never, 1, '2', true, boolean], 1, 2>; // [never,1]
type S4 = Slice<[any, never, 1, '2', true, boolean], 2>; // [1,'2',true,boolean]
type S5 = Slice<[any], 2>; // []
type S6 = Slice<[], 0>; // []

// splice 删除并替换元素
type Splice<
  Arr extends any[],
  Start extends number,
  Count extends number = 0,
  Replace extends any[] = [],
  StartCount extends any[] = [],
  CountArr extends any[] = [],
  Result extends any[] = []
> = StartCount['length'] extends Start
  ? CountArr['length'] extends Count
    ? [...Result, ...Replace, ...Arr]
    : Arr extends [infer First, ...infer Rest]
    ? Splice<Rest, Start, Count, Replace, StartCount, [...CountArr, 0], Result>
    : Result
  : Arr extends [infer First, ...infer Rest]
  ? Splice<
      Rest,
      Start,
      Count,
      Replace,
      [...StartCount, 0],
      CountArr,
      [...Result, First]
    >
  : Result;

type SP1 = Splice<[string, number, boolean, null, undefined, never], 0, 2>; // [boolean,null,undefined,never]
type SP2 = Splice<[string, number, boolean, null, undefined, never], 1, 3>; // [string,undefined,never]
type SP3 = Splice<
  [string, number, boolean, null, undefined, never],
  1,
  2,
  [1, 2, 3]
>; // [string,1,2,3,null,undefined,never]

export {};

Type Operations

// 获取对象类型中的可选属性的联合类型
// @ts-nocheck
type OptionalKeys<T> = keyof {
  [K in keyof T as T[K] extends Required<T>[K] ? never : K]: T[K];
};

type a1 = OptionalKeys<{
  foo: number | undefined;
  bar?: string;
  flag: boolean;
}>; // bar

type a2 = OptionalKeys<{ foo: number; bar?: string }>; // bar

type a3 = OptionalKeys<{ foo: number; flag: boolean }>; // never

type a4 = OptionalKeys<{ foo?: number; flag?: boolean }>; // foo|flag

type a5 = OptionalKeys<{}>; // never

// 获取对象类型中的必选属性
type PickRequired<T> = {
  [K in keyof T as T[K] extends Required<T>[K] ? K : never]: T[K];
};

type p1 = PickRequired<{
  foo: number | undefined;
  bar?: string;
  flag: boolean;
}>; // {foo:number|undefined, flag:boolean}

type p2 = PickRequired<{ foo: number; bar?: string }>; // {foo:number}

type p3 = PickRequired<{ foo: number; flag: boolean }>; // {foo:number,flag:boolean}

type p4 = PickRequired<{ foo?: number; flag?: boolean }>; // {}

type p5 = PickRequired<{}>; // {}

// 判断类型是否是 never
type IsNever<T> = [T] extends [never] ? true : false;

type A = IsNever<never>; // true
type B = IsNever<string>; // false
type C = IsNever<undefined>; // false
type D = IsNever<any>; // false

// 判断是否为没有属性的对象类型 {}
// @ts-nocheck
type x1 = keyof {}; // never

type IsEmptyType<T> = T extends object
  ? keyof T extends never
    ? true
    : false
  : false;

type EA = IsEmptyType<string>; // false
type EB = IsEmptyType<{ a: 3 }>; // false
type EC = IsEmptyType<{}>; // true
type ED = IsEmptyType<any>; // false
type EE = IsEmptyType<object>; // false
type EF = IsEmptyType<Object>; // false
type EG = IsEmptyType<unknown>; // false

// 判断类型是否是 any
// 可以将 unknown 赋予给 any
type IsAny<T> = unknown extends T ? true : false;

type IA = IsAny<string>; // false
type IB = IsAny<any>; // true
type IC = IsAny<unknown>; // false
type ID = IsAny<never>; // false

// @ts-nocheck
interface Action<T> {
  payload?: T;
  type: string;
}

interface Module {
  count: number;
  message: string;
  asyncMethod<T, U>(input: Promise<T>): Promise<Action<U>>;
  syncMethod<T, U>(action: Action<T>): Action<U>;
}

// 这个要求的结果
type Result = {
  asyncMethod<T, U>(input: T): Action<U>;
  syncMethod<T, U>(action: T): Action<U>;
};

type Connect<T> = {
  [K in keyof T]: T[K] extends (
    input: Promise<infer A>
  ) => Promise<Action<infer B>>
    ? (input: A) => Action<B>
    : T[K] extends (action: Action<infer A>) => Action<infer B>
    ? (action: A) => Action<B>
    : T[K];
};

type F = Connect<Module>;

// 将联合类型转换为交叉类型
// @ts-nocheck
type UnionToIntersection<U> = (
  U extends any ? (arg: U) => any : never
) extends (arg: infer I) => any
  ? I
  : never;

type UA = UnionToIntersection<{ a: string } | { b: string } | { c: string }>; // {a: string} & {b: string} & {c: string}

// 联合类型转换为元组类型
// @ts-nocheck
type UnionToTuple<T> = UnionToIntersection<
  T extends any ? (t: T) => T : never
> extends (_: any) => infer W
  ? [...UnionToTuple<Exclude<T, W>>, W]
  : [];

type a1 = UnionToTuple<1 | 2 | 3>; // [1,2,3]
type a2 = UnionToTuple<1 | 2 | boolean | string>; // [1,2,boolean,string]

export {};

主题测试文章,只做测试使用。发布者:Walker,转转请注明出处:https://walker-learn.xyz/archives/4412

(0)
Walker的头像Walker
上一篇 Mar 27, 2025 15:01
下一篇 Apr 6, 2025 22:23

Related Posts

  • Go Engineer Systematic Course 001 [Study Notes]

    Transitioning: Reasons for a rapid, systematic transition to Go engineering:
    To improve CRUD operations.
    To gain experience with self-developed frameworks.
    For colleagues aiming to deepen technical expertise, specializing and refining requirements.
    To advance engineering practices, developing good coding standards and management capabilities.

    The Importance of Engineering

    Expectations for Senior Developers:
    Good code standards.
    Deep understanding of underlying principles.
    Familiarity with architecture.
    Familiarity with K8s basic architecture.
    Expanding knowledge breadth and depth, and a standardized development system.

    Four Major Stages:
    Go language fundamentals.
    Microservice development (e-commerce project practical experience).
    Self-developed microservices.
    Self-developed, then re...

    Personal Nov 25, 2025
    28100
  • In-depth Understanding of ES6 007 [Study Notes]

    Set and Map Collections. In JS, there is an `in` operator that can determine if a property exists in an object without needing to read the object's value, returning true if it exists. However, the `in` operator also checks the object's prototype chain, so using this method is only relatively safe when the object's prototype is null. Set Collection: `let set = new Set()` `set.add(5)` `set.add("5")` `console.log(s…`

    Personal Mar 8, 2025
    1.2K00
  • In-depth Understanding of ES6 005 [Study Notes]

    Destructuring: Making data access more convenient. If you declare variables using `var`, `let`, or `const` with destructuring, you must provide an initializer (i.e., the value on the right side of the equals sign). The following will cause an error:
    // Syntax error `var {tyep,name}`
    // Syntax error `let {type,name}`
    // Syntax error `const {type,name}`
    To assign values to already declared variables using destructuring, consider the following:
    `let node = { type:&qu...`

    Personal Mar 8, 2025
    1.2K00
  • Node In-depth and Easy to Understand (Sheng Siyuan Education) 002 [Study Notes]

    Node's package management and loading mechanisms: npm search xxx, npm view xxx, npm install xxx. Node.js file system operation APIs: Node.js's `fs` module provides synchronous (Sync) and callback/Promise-based asynchronous APIs for operating on local files and directories. Commonly used capabilities in daily development include reading, writing, appending, deleting, traversing directories, listening for changes, and so on. The following examples are based on C...

    Personal Nov 24, 2025
    23100
  • In-depth Understanding of ES6 011 [Learning Notes]

    Promises and Asynchronous Programming

    Because the execution engine is single-threaded, it needs to track the code that is about to run. This code is placed in a task queue. Whenever a piece of code is ready to execute, it is added to the task queue, and whenever a piece of code in the engine finishes execution, the event loop executes the next task in the queue. A Promise acts as a placeholder for the result of an asynchronous operation. It doesn't subscribe to an event or pass a callback function to the target function. Instead, it allows the function to return a Promise, like this...

    Personal Mar 8, 2025
    1.1K00
EN
简体中文 繁體中文 English
欢迎🌹 Coding never stops, keep learning! 💡💻 光临🌹