1. 什么是 TypeScript,为什么要用它?
- TypeScript 是一种静态类型的面向对象的编程语言,它是 JavaScript 框架 之一,它添加了可选的静态类型和其他功能,由 Microsoft 开发和维护。
- TypeScript 可以让我们的代码更易于维护和扩展,并提供更好的工具和编辑器支持。
2. TypeScript基本类型?
- 基础类型:Number、Null、Boolean、Undefined、String、Symbol、Enum(枚举)、Any
- 引用类型:Object、Array、Function
- 其他类型:Never、Unknown、交叉类型、联合类型、字面量类型、索引类型
拓展
1. null 与 undefined的区别
JavaScript:
null:有值。且值为空值
undefined:已声明、未赋值
strictNullChecks
2. void
主要用于指定当前函数是否会有返回值
3. .d.ts和ts文件有什么区别?
.ts
文件是TypeScript的主要实现文件,包含可执行的代码和类型信息;而.d.ts
文件则是类型声明文件,只包含类型信息,用于为TypeScript编译器提供必要的类型信息,以便进行静态类型检查和其他开发辅助功能。4. unknown和any的区别?
any:可以给任意类型值赋值,也可以被任意类型赋值。
unknonw:只能被赋值,不能赋值别人。
3. TypeScript 与 JavaScript 有何不同?
超集的,意味着ts支持所有的js语法类型。并且ts有严格的类型检测,会在编译时检测数据错误类型。
4. TypeScript 的主要特点是什么?
- 静态类型系统
- 类型系统允许开发者定义变量、函数参数和函数返回值的类型,从而提供了编译时的类型检查。
- 这有助于减少运行时的错误,并增强代码的可读性和可维护性。
- 面向对象(OOP)
- 支持接口、类、继承
- 模块系统
- 支持 ES6 模块系统,允许开发者将代码拆分成可重用的模块
- 装饰器
- 装饰器提供了一种声明式的方式来修改类、方法、属性或参数的行为。
- 泛型
- ts支持泛型允许开发者创建可重用的组件,这些组件可以工作于多种数据类型,同时也可以在单个函数中处理多种类型的数据。
4. TypeScript中类型层级关系?
5. 如何在 TypeScript 中定义类?
TypeScript 中的类可以使用 class 关键字定义,后跟类名。可以使用构造函数方法和公共或私有关键字将属性和方法添加到类中。
class Person {
constructor(public name: string) {} greet() {
console.log(`Hello, my name is ${this.name}`);
}
}
6. 如何在 TypeScript 中定义和导入/导出模块?
TypeScript 中的模块可以在声明类、函数或变量之前使用 export 关键字来定义。然后可以使用 import 关键字以及包含导出的文件的路径将这些导出导入到另一个文件中。
// math.ts
export function add(a: number, b: number): number {
return a + b;
}
// main.ts
import { add } from './math';
console.log(add(1, 2)); // 3
7. 在 TypeScript 中如何定义和使用命名空间?
可以使用 namespace 关键字后跟命名空间名称来定义 TypeScript 命名空间。
您可以使用声明关键字将代码添加到命名空间。
namespace MyApp {
export function doSomething() {
console.log('Doing something');
}
}
MyApp.doSomething(); // Doing something
8. 如何使用TypeScript创建和使用装饰器?
- 装饰器:TypeScript 装饰器是一种向类、方法或属性添加额外行为的方法。
装饰器作为函数实现,可以使用@符号来应用。 - 创建和使用装饰器
function Logger(target: any, propertyKey: string) {
console.log(`Calling ${propertyKey}`);
}
class MyClass {
@Logger
greet() {
console.log('Hello');
}
}
const instance = new MyClass();
instance.greet();
// Calling greet
// Hello
9. TypeScript 中如何定义和使用泛型?
TypeScript 中的泛型是在函数、类和接口声明中使用方括号 <> 定义的,带有类型的占位符。并且可以在使用函数、类或接口时指定形状。
function identity<T>(arg: T): T {
return arg;
}
const result = identity<string>('Hello');
console.log(result); // Hello
10.如何在 TypeScript 中使用 async/await?
async function fetchData(): Promise<string> {
const response = await fetch('https://api.example.com');
const data = await response.json();
return data;
}
fetchData().then(data => {
console.log(data);
});
11.TypeScript 如何与其他工具和库集成?
TypeScript 可以与 Angular 和 React 等流行的前端框架以及用于服务器端开发的 Node.js 等各种工具和库一起使用。
TypeScript 代码可以编译成纯 JavaScript,使其与任何支持 JavaScript 的环境兼容。
12.TypeScript中逆变和协变
- 协变:关注返回值的类型(输出),简单来说,如果函数A的返回类型是类型B的子类型,那么函数A可以视为函数B的协变。
class Animal {
speak(): void {
console.log('The animal speaks');
}
}
class Dog extends Animal {
bark(): void {
console.log('Woof!');
}
}
function getAnimal(): Animal {
return new Animal();
}
function getDog(): Dog {
return new Dog();
}
// 假设我们有一个函数,它接受一个返回Animal类型的函数
function useAnimalFunction(fn: () => Animal): void {
const animal = fn();
animal.speak();
}
// 因为getDog()返回的是Dog类型,它是Animal的子类型,所以这里协变是成立的
useAnimalFunction(getDog); // 这是允许的
- 逆变:关注参数类型(输入)。与协变相反,逆变描述的是函数参数类型的“反向”关系。如果一个函数A的参数类型是类型B的超类型,那么函数A可以视为函数B的逆变。
function feedAnimal(animal: Animal): void {
console.log('Feeding the animal');
}
// 如果我们有一个只接受Dog类型参数的函数,我们不能直接将其赋值给接受Animal类型参数的函数
// 因为这会导致类型不安全(即,我们可能会尝试将一个不是Dog的动物传递给feedDog函数)
// function feedDog(dog: Dog): void { ... }
// feedAnimal = feedDog; // 这是不允许的
// 但是,我们可以通过包装或使用类型守卫等方式来模拟逆变
function safeFeedDog(maybeDog: Animal): void {
if (maybeDog instanceof Dog) {
// 在这里,我们可以安全地假设maybeDog是一个Dog
console.log('Feeding the dog');
// ... 执行针对Dog的特定操作
} else {
// 如果不是Dog,我们可以选择不执行任何操作或抛出错误
console.log('The animal is not a dog and cannot be fed with dog food');
}
}
// 然后我们可以安全地传递一个Animal给safeFeedDog
safeFeedDog(new Animal()); // 输出:'The animal is not a dog and cannot be fed with dog food'
safeFeedDog(new Dog()); // 输出:'Feeding the dog'
13. TypeScript中的静态属性
静态属性(方法),也称为类属性。使用静态属性无需创建实例,通过类即可直接使用
静态属性(方法)使用static开头
class Tools{
static PI = 3.1415926;
static sum(num1: number, num2: number){
return num1 + num2
}
}
console.log(Tools.PI);
console.log(Tools.sum(123, 456));
14 .TypeScript中重写
class Animal{
name: string;
age: number;
constructor(name: string, age: number){
this.name = name;
this.age = age;
}
run(){
console.log(`父类中的run方法!`);
}
}
class Dog extends Animal{
bark(){
console.log(`${this.name}在汪汪叫!`);
}
run(){
console.log(`子类中的run方法,会重写父类中的run方法!`);
}
}
const dog = new Dog('旺财', 4);
dog.bark();
15. TypeScript中内置泛型工具Pick、Omit
- Pick
- 从类型对象中 取出指定的属性类型
- 使用方式:Pick<类型对象,要拾取的属性1,要拾取的属性2......>
export interface User {
account: string
avatar: string
id: string
mobile: string
token: string
}
// 使用Pick泛型工具: 抽取 id 和 token
export type PickUserTest = Pick<User, 'id', 'token'>
// 结果:PickUserTest === {id: string,token: string}
- Omit
- 从类型对象中排出 指定的属性类型,得到剩余的属性类
- 使用方式:Omit<类型对象,排除的属性1,排除的属性2.....>
export interface User {
account: string
avatar: string
id: string
mobile: string
token: string
}
// 使用 Omit 泛型工具: 去掉 token 和 mobile
export type OmitUserTest = Omit<User, 'token','mobile'>
// 结果:OmitUserTest === {account: string,avatar: string,id: string}
16.TypeScript中的三元操作符“?:”
interface User {
username?: string;
}
代码中,{username?: string} 是一个类型注释,它表示该属性可以是一个字符串类型的值,也可以是不存在的值(即 undefined)。