二、【typescript】必须要掌握的概念、常见TS面试题

16.映射类型中的“键重新映射”和“值重新映射”是什么?为每个提供示例。

回答:“键重映射”和“值重映射”是 TypeScript 中映射类型的两个特性。

“键重新映射”允许您使用 as 关键字更改现有类型的键。这是一个例子:

interface Person {
  name: string;
  age: number;
}
type MappedPerson = { [K in keyof Person as new_${K}]: Person[K] };
const john: MappedPerson = { new_name: 'John', new_age: 30 };
// 在此示例中,Person 的键被重新映射为具有前缀“new_”。
// “值重新映射”允许您使用条件类型更改现有类型的值。这是一个例子:
type ValueRemapped = T extends 'a' ? 'x' : T extends 'b' ? 'y' : 'z'; 
type Result = ValueRemapped<'a' | 'b' | 'c'>; 
// Result: 'x' | 'y' | 'z' 在此示例中,值“a”、“b”和“c”分别重新映射为“x”、“y”和“z”。
17.解释 TypeScript 中的“Pick”实用程序类型。举个例子。

答案:TypeScript 中的“Pick”实用程序类型允许您通过从现有类型中选择特定属性来创建新类型。它有助于创建现有类型的子集。这是一个例子:

interface Person {
  name: string;
  age: number;
  city: string;
}
type PersonInfo = Pick<Person, 'name' | 'age'>;
const john: PersonInfo = { name: 'John', age: 30 };
// 在此示例中,PersonInfo 是仅包含 Person 接口中的“name”和“age”属性的类型。
18.TypeScript 中的“Omit”实用程序类型是什么?它是如何工作的?举个例子。

答案:TypeScript 中的“Omit”实用程序类型允许您通过从现有类型中排除特定属性来创建新类型。它有助于创建删除了某些属性的类型。这是一个例子:

interface Person {
  name: string;
  age: number;
  city: string;
}
type PersonWithoutCity = Omit<Person, 'city'>;
const john: PersonWithoutCity = { name: 'John', age: 30 };
// 在此示例中,PersonWithoutCity 是一种从 Person 接口中排除“city”属性的类型。
19.TypeScript 中的“条件映射类型”是什么?举个例子。

答:条件映射类型将条件类型和映射类型结合起来,根据条件执行类型转换。它们允许您根据现有类型的属性创建动态类型。这是一个例子:

interface Person {
  name: string;
  age: number;
}
type MappedConditional = {  
  [K in keyof T]: T[K] extends number ? string : T[K]; 
}; 
const john: MappedConditional = { name: 'John', age: '30' }; 
// 在此示例中,MappedConditional 是一个条件映射类型,它将 Person 的数字属性转换为字符串。
20.条件类型中“keyof”和“in”关键字的用途是什么?举个例子。

答案:条件类型中的“keyof”关键字用于获取对象类型的键的并集。它允许您以类型安全的方式使用对象的键。“in”关键字检查属性键是否存在于从“keyof”获得的键的并集中。这是一个例子:

type CheckKey<T, K extends keyof T> = K extends 'name' ? true : false;
interface Person {
  name: string;
  age: number;
}
type IsNameKey = CheckKey<Person, 'name'>; // Result: true
type IsCityKey = CheckKey<Person, 'city'>; // Result: false
在此示例中,CheckKey 是一个条件类型,用于检查提供的键是否为“name”。
21.解释 TypeScript 中的“排除”实用程序类型。举个例子。

答案:TypeScript 中的“排除”实用程序类型允许您通过从联合中排除某些类型来创建新类型。它有助于创建联合类型的子集。这是一个例子:

type Color = 'red' | 'green' | 'blue';
type PrimaryColors = Exclude<Color, 'green' | 'blue'>;
const primary: PrimaryColors = 'red'; // Okay
const invalidColor: PrimaryColors = 'green'; // Error: Type '"green"' is not assignable to type 'PrimaryColors'.
// 在此示例中,PrimaryColors 是一种从颜色联合中排除“绿色”和“蓝色”颜色的类型。
22.TypeScript 中的“模板文字类型”是什么?举个例子。

答案:TypeScript 中的模板文字类型允许您使用模板文字语法来操作类型中的字符串。它们提供了一种基于字符串模式创建复杂类型的方法。这是一个例子:

type Greeting = Hello, ${T}!; 
type GreetJohn = Greeting<'John'>; // Result: "Hello, John!" 
type GreetJane = Greeting<'Jane'>; // Result: "Hello, Jane!" 
// 在此示例中,Greeting 是一个模板文字类型,它根据提供的名称生成问候语。
23.解释条件类型中的“infer”关键字。举个例子。 就是自动推断出的类型

答案:条件类型中的“infer”关键字用于从条件类型中的另一种类型推断出类型。它允许您捕获类型并将其分配给类型变量。这是一个例子:

type ReturnType = T extends (...args: any[]) => infer R ? R : never; 
function add(a: number, b: number): number {   return a + b; } 
type AddReturnType = ReturnType; // Result: number 
// 在此示例中,ReturnType 是一个条件类型,它使用“infer”关键字推断函数的返回类型。
24.TypeScript 中的“keyof”和“typeof”关键字有何用途?为每个提供示例。

答:“keyof”关键字用于获取对象类型的键的并集,“typeof”关键字用于获取值的类型。以下是每个示例:

interface Person {
  name: string;
  age: number;
}
type PersonKeys = keyof Person; // Result: "name" | "age"
const john = { name: 'John', age: 30 };
type JohnType = typeof john; // Result: { name: string, age: number }
在第一个示例中,PersonKeys 是表示 Person 接口的键联合的类型。在第二个示例中,JohnType 是表示 john 对象类型的类型。
25.TypeScript 中的“const 断言”是什么?举个例子。

答案:TypeScript 中的“Const 断言”允许您通知编译器特定的文字表达式应被视为文字而不是扩展类型。这是一个例子:

function getConfig() {
  const config = {
    apiUrl: 'https://api.example.com',
    timeout: 5000,
  } as const;
  return config;
}
const config = getConfig();
// config is inferred as:
// {
//   readonly apiUrl: "https://api.example.com";
//   readonly timeout: 5000;
// }
在此示例中,由于 as const 断言,config 对象被视为具有只读属性的常量对象。
26.TypeScript 中的“私有”和“受保护”访问修饰符是什么?为每个提供示例。

答案:“Private”和“protected”是 TypeScript 中的访问修饰符,用于控制类成员的可见性和可访问性。

private 只可以在类的内部访问,实例 和 子类中均不能访问

protected 可以在类 或 子类内部访问,不能在实例中访问

class Person {
  private name: string;
  protected age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
  greet() {
    console.log(Hello, my name is ${this.name}, and I am ${this.age} years old.);
  }
}
class Employee extends Person {
  private salary: number;
  constructor(name: string, age: number, salary: number) {
    super(name, age);
    this.salary = salary;
  }
  showSalary() {
    console.log(My salary is ${this.salary}.);
  }
}
const john = new Person('John', 30);
console.log(john.name); // Error: Property 'name' is private and only accessible within class 'Person'.
console.log(john.age); // Error: Property 'age' is protected and only accessible within class 'Person' and its subclasses.
const employee = new Employee('Jane', 25, 50000);
employee.greet(); // Output: "Hello, my name is Jane, and I am 25 years old."
employee.showSalary(); // Output: "My salary is 50000."
console.log(employee.salary); // Error: Property 'salary' is private and only accessible within class 'Employee'.
在此示例中,name 属性具有“private”访问修饰符,age 属性有“protected”访问修饰符。工资属性是 Employee 类私有的。

延伸阅读:TypeScript 官方手册——类(https://www.typescriptlang.org/docs/handbook/classes.html)

27.解释 TypeScript 条件类型中的“keyof T extends K”构造。举个例子。

答案:TypeScript 条件类型中的“keyof T extends K”构造用于使用“extends”关键字根据指定条件过滤对象类型的键。这是一个例子:

type FilterProperties<T, K> = {
  [P in keyof T as T[P] extends K ? P : never]: T[P];
};
interface Person {
  name: string;
  age: number;
  email: string;
}
type StringProperties = FilterProperties<Person, string>;
// Result: {
//   name: string;
//   email: string;
// }
type NumberProperties = FilterProperties<Person, number>;
// Result: {
//   age: number;
// }
在此示例中,FilterProperties 是一个条件映射类型,它根据值类型过滤 Person 的属性。
28.TypeScript 中的“mixins”是什么?举个例子。 就是继承吧 extends

答案:TypeScript 中的 Mixins 允许您通过将某个类与一个或多个其他类组合来向该类添加行为。它支持代码重用和组合。这是一个 mixin 的例子:

class Printable {
  print() {
    console.log(this.toString());
  }
}
class MyObject {
  constructor(private name: string) {}
  toString() {
    return Object: ${this.name};
  }
}
interface MyObject extends Printable {}
const myObj = new MyObject('example');
myObj.print(); // Output: "Object: example"
在此示例中,Printable 类充当 mixin,将 print 方法添加到 MyObject 类。
29.解释 TypeScript 中“声明合并”的概念。举个例子。

回答:TypeScript 中的“声明合并”是编译器将同一实体的多个声明合并到单个定义中的过程。它允许您扩展接口、函数、类和枚举。

interface Person {
  name: string;
}
interface Person {
  age: number;
}
const john: Person = { name: 'John', age: 30 };
console.log(john); // Output: { name: 'John', age: 30 }
在此示例中,编译器将两个 Person 接口合并为一个定义,允许 john 同时具有 name 和age 属性。
30.TypeScript 中的“noUncheckedIndexedAccess”编译器选项是什么?为什么它很有用?举个例子。

答案:TypeScript 中的“noUncheckedIndexedAccess”编译器选项用于在使用索引访问属性时捕获潜在的未定义或空值。它通过避免运行时错误来帮助提高代码安全性。

// tsconfig.json
{
  "compilerOptions": {
    "noUncheckedIndexedAccess": true
  }
}
这是一个例子:
const data: { [key: string]: number } = {
  apple: 1,
  banana: 2,
};
const fruit = 'pear';
const count = data[fruit]; // Error: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ apple: number; banana: number; }'.
在此示例中,启用“noUncheckedIndexedAccess”会引发错误,因为 data[fruit] 可能未定义或为 null

进一步阅读:TypeScript 编译器选项(https://www.typescriptlang.org/tsconfig#noUncheckedIndexedAccess)

  • 12
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值