本文详细介绍了TypeScript的基础概念与语法,包括变量声明、类型推断、接口定义和类的使用等。文章还提供了TS大厂面试真题的实际演练和解析,帮助读者深入理解并掌握关键知识点。此外,文章还分享了面试中的技巧与策略,帮助读者更好地准备和应对TS相关的技术面试。
在 TypeScript 中,可以通过 let
或 const
关键字来声明变量。声明变量时,可以指定类型,也可以使用类型推断。
// 显式声明类型 let age: number = 25; const name: string = "John Doe"; // 类型推断 let message = "Hello, TypeScript!";
TypeScript 通过类型推断来确定变量的类型。如果在声明时没有明确指定类型,TypeScript 会根据赋值来确定变量的类型。
let message = "Hello, TypeScript!"; // 类型推断为 string console.log(message);
在 TypeScript 中,变量声明会被提升到其所在作用域的顶部。这意味着可以在声明之前使用变量,但必须在声明之前声明它们。
console.log(age); // 输出 undefined let age = 25;
与变量不同,const
声明不会提升。如果在声明之前使用 const
,会抛出引用错误。
// console.log(name); // 抛出 ReferenceError const name = "John Doe";
在 TypeScript 中,可以通过 Array
类型或数组类型注解来声明数组。
let numbers: number[] = [1, 2, 3, 4, 5]; let names: Array<string> = ["Alice", "Bob", "Charlie"];
元组允许你声明具有固定数量和类型元素的数组。元组中的元素可以有不同的类型。
let user: [string, number]; user = ["Alice", 25]; console.log(user[0], user[1]); // 输出 Alice 25
在 TypeScript 中,可以使用函数声明来定义函数。函数声明可以指定参数类型和返回类型。
function add(a: number, b: number): number { return a + b; } console.log(add(2, 3)); // 输出 5
函数表达式将函数作为值赋给一个变量。
let multiply = function (a: number, b: number): number { return a * b; }; console.log(multiply(2, 3)); // 输出 6
在函数中,可以使用 ?
符号来定义可选参数。也可以为参数指定默认值。
function greet(name: string, message?: string): void { console.log(`Hello, ${name}! ${message ? message : "Have a nice day!"}`); } greet("Alice"); // 输出 Hello, Alice! Have a nice day! greet("Bob", "Good morning!"); // 输出 Hello, Bob! Good morning!
接口用于定义对象的结构。接口可以包含属性、方法和索引签名。
interface User { name: string; age: number; greet(): void; } let user: User = { name: "Alice", age: 25, greet() { console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`); } }; user.greet(); // 输出 Hello, my name is Alice and I am 25 years old.
接口中的属性可以被定义为可选,使用 ?
符号。
interface User { name: string; age?: number; // 可选属性 } let user: User = { name: "Alice" }; console.log(user.name); // 输出 Alice console.log(user.age); // 输出 undefined
接口中的索引签名用于定义对象中键和值的类型。
interface User { [key: string]: any; } let user: User = { name: "Alice", age: 25 }; console.log(user.name); // 输出 Alice console.log(user.age); // 输出 25
类是对象的蓝图,可以定义类的属性、方法和构造函数。
class User { name: string; 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.`); } } let user = new User("Alice", 25); user.greet(); // 输出 Hello, my name is Alice and I am 25 years old.
类可以通过 extends
关键字继承另一个类。继承的类会继承父类的所有属性和方法。
class Admin extends User { role: string; constructor(name: string, age: number, role: string) { super(name, age); this.role = role; } greet() { console.log(`Hello, my name is ${this.name}, I am ${this.age} years old and my role is ${this.role}.`); } } let admin = new Admin("Bob", 30, "Admin"); admin.greet(); // 输出 Hello, my name is Bob, I am 30 years old and my role is Admin.
泛型允许你编写可复用的函数或类,这些函数或类可以操作多种类型的值。
function identity<T>(arg: T): T { return arg; } let output = identity<string>("Hello, TypeScript!"); console.log(output); // 输出 Hello, TypeScript!
泛型接口允许你定义可以用于多种类型的接口。
interface GenericIdentity<T> { (arg: T): T; } let identity: GenericIdentity<number> = (arg: number) => arg; console.log(identity(25)); // 输出 25
泛型约束用于限制泛型类型,使其满足某些条件。
interface Lengthwise { length: number; } function identity<T extends Lengthwise>(arg: T): T { console.log(arg.length); // 长度属性确保了类型具有 length 属性 return arg; } let output = identity({ length: 10, value: "Hello" }); console.log(output); // 输出 { length: 10, value: "Hello" }
在TypeScript中,变量声明会被提升到其所在作用域的顶部。这意味着可以在声明之前使用变量,但必须在声明之前声明它们。对于 let
和 const
声明来说,变量在声明之前会被提升为 undefined
,而 const
声明不会提升。
console.log(age); // 输出 undefined let age = 25;
// console.log(name); // 抛出 ReferenceError const name = "John Doe";
类型推断是TypeScript根据赋值自动确定变量类型的过程。如果没有明确指定类型,TypeScript会根据赋值来确定变量的类型。
let message = "Hello, TypeScript!"; // 类型推断为 string console.log(message);
接口定义了对象的结构,接口可以包含属性、方法和索引签名。而类是对象的蓝图,可以定义类的属性、方法和构造函数。接口用于定义对象的形状,而类用于创建具体的对象实例。
interface User { name: string; age: number; greet(): void; } class UserClass { name: string; 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.`); } }
泛型允许你编写可复用的函数或类,这些函数或类可以操作多种类型的值。泛型通过指定类型参数在函数或类定义中传递类型。
function identity<T>(arg: T): T { return arg; } let output = identity<number>(25); console.log(output); // 输出 25
类型断言用于告诉编译器一个值具有某个特定的类型。类型断言有两种形式:<Type>expression
和 expression as Type
。
let someValue: any = "abc"; let strLength: number = (someValue as string).length;
面试官可能会考察你对TypeScript类型系统和类型推断的理解,包括类型推断如何工作,如何在代码中使用类型推断。
// 示例代码 let age: number = 25; const name: string = "John Doe"; // 类型推断 let message = "Hello, TypeScript!"; console.log(message);
接口与类的概念是面试中常见的考察点,包括它们的区别、如何定义接口和类、如何使用接口和类。
// 示例代码 interface User { name: string; age: number; greet(): void; } class UserClass { name: string; 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.`); } }
面试官可能会考察你对泛型的理解,包括如何定义泛型函数和泛型类,以及如何使用泛型约束。
// 示例代码 function identity<T>(arg: T): T { return arg; } let output = identity<number>(25); console.log(output);
面试官可能会考察你的代码风格和代码质量,包括最佳实践、如何编写可维护的代码、如何避免常见的陷阱和错误。
// 示例代码 function sumArray(arr: number[]): number { return arr.reduce((acc, val) => acc + val, 0); } let numbers = [1, 2, 3, 4, 5]; let sum = sumArray(numbers); console.log(sum);
面试官可能会考察你在实际项目中使用TypeScript的经验,包括你如何在项目中使用TypeScript,你遇到过哪些挑战,你是如何解决这些挑战的。
// 示例代码 class Admin extends User { role: string; constructor(name: string, age: number, role: string) { super(name, age); this.role = role; } greet() { console.log(`Hello, my name is ${this.name}, I am ${this.age} years old and my role is ${this.role}.`); } } let admin = new Admin("Bob", 30, "Admin"); admin.greet();
题目描述:给定一个数组,编写一个函数将数组中的元素类型推断为 number,并返回数组的和。
function sumArray(arr: any[]): number { return arr.reduce((acc, val) => acc + val, 0); } let numbers = [1, 2, 3, 4, 5]; let sum = sumArray(numbers); console.log(sum); // 输出 15
题目描述:给定一个对象,编写一个函数检查对象是否包含某个属性,并返回该属性的值。
function getProperty(obj: any, key: string): any { return key in obj ? obj[key] : undefined; } let user = { name: "Alice", age: 25 }; let name = getProperty(user, "name"); let address = getProperty(user, "address"); // undefined console.log(name); // 输出 Alice console.log(address); // 输出 undefined
题目描述:给定一个对象和一个键,编写一个函数将对象中的键值对添加到另一个对象中。
function addProperty(target: any, key: string, value: any): void { target[key] = value; } let user = {}; addProperty(user, "name", "Alice"); addProperty(user, "age", 25); console.log(user); // 输出 { name: "Alice", age: 25 }
题目描述:给定一个泛型类型,编写一个函数将对象中的键值对添加到另一个对象中。
function addProperty<T extends object, K extends keyof T>(target: T, key: K, value: T[K]): void { target[key] = value; } let user = {} as { name: string, age: number }; addProperty(user, "name", "Alice"); addProperty(user, "age", 25); console.log(user); // 输出 { name: "Alice", age: 25 }
题目描述:给定一个数组,编写一个函数将数组中的元素类型推断为 number,并返回数组的平均值。
function averageArray(arr: any[]): number { return arr.reduce((acc, val) => acc + val, 0) / arr.length; } let numbers = [1, 2, 3, 4, 5]; let avg = averageArray(numbers); console.log(avg); // 输出 3
在使用TypeScript时,尽量避免手动转换类型,尽量使用类型推断和类型断言。手动转换类型会导致代码更难以维护和理解。
let someValue: any = "abc"; let length = (someValue as string).length; console.log(length);
在编写函数和类时,使用泛型可以提高代码的复用性。泛型允许你编写可复用的代码,这些代码可以操作多种类型的值。
function identity<T>(arg: T): T { return arg; }
使用接口定义对象的形状是一种良好的实践。接口可以定义对象的结构,包括属性、方法和索引签名。
interface User { name: string; age: number; }
使用类创建具体的对象实例是一种良好的实践。类是对象的蓝图,可以定义类的属性、方法和构造函数。
class User { name: string; age: number; constructor(name: string, age: number) { this.name = name; this.age = age; } }
使用最佳实践编写可维护的代码是一种良好的实践。最佳实践包括代码风格、命名约定、注释和文档等。
function averageArray(arr: number[]): number { return arr.reduce((acc, val) => acc + val, 0) / arr.length; }
掌握TypeScript的基础概念和语法是面试的重要准备。确保你理解变量与类型、数组与元组、函数、接口、类、泛型等基本概念。
// 示例代码 let age: number = 25; const name: string = "John Doe"; // 类型推断 let message = "Hello, TypeScript!"; console.log(message);
练习编写高质量代码是面试的重要准备。确保你能够编写清晰、简洁、可维护的代码。练习编写可复用的代码,避免重复造轮子。
// 示例代码 function averageArray(arr: number[]): number { return arr.reduce((acc, val) => acc + val, 0) / arr.length; } let numbers = [1, 2, 3, 4, 5]; let avg = averageArray(numbers); console.log(avg);
准备项目经验与实际应用是面试的重要准备。确保你能够描述你在实际项目中使用TypeScript的经验,包括你遇到的挑战和你是如何解决这些挑战的。
// 示例代码 class Admin extends User { role: string; constructor(name: string, age: number, role: string) { super(name, age); this.role = role; } greet() { console.log(`Hello, my name is ${this.name}, I am ${this.age} years old and my role is ${this.role}.`); } } let admin = new Admin("Bob", 30, "Admin"); admin.greet();
保持积极的心态是面试的重要准备。面试可能会遇到一些挑战,但保持积极的心态可以帮助你更好地应对这些挑战。相信自己的能力,保持自信。
// 示例代码 let age: number = 25; const name: string = "John Doe"; console.log(`Hello, ${name}! Your age is ${age}.`);
练习模拟面试是面试的重要准备。模拟面试可以帮助你熟悉面试的过程,提高你的面试技巧。可以邀请朋友或同事帮助你进行模拟面试。
// 示例代码 function averageArray(arr: number[]): number { return arr.reduce((acc, val) => acc + val, 0) / arr.length; } let numbers = [1, 2, 3, 4, 5]; let avg = averageArray(numbers); console.log(avg);
保持耐心与专注是面试的重要准备。面试可能会遇到一些挑战,但保持耐心与专注可以帮助你更好地应对这些挑战。保持冷静,认真回答每一个问题。
// 示例代码 function sumArray(arr: number[]): number { return arr.reduce((acc, val) => acc + val, 0); } let numbers = [1, 2, 3, 4, 5]; let sum = sumArray(numbers); console.log(sum);
准备常见面试问题是面试的重要准备。确保你能够回答一些常见的面试问题,包括解释TypeScript中的变量声明、类型推断、接口与类的区别、泛型的概念等。
// 示例代码 function identity<T>(arg: T): T { return arg; } let output = identity<string>("Hello, TypeScript!"); console.log(output);