TypeScript 面试题及详细答案 100题 (41-50)-- 函数类型
《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。
文章目录
- 一、本文面试题目录
- 41. 如何在TypeScript中定义函数的参数类型和返回值类型?
- 42. 函数的可选参数和默认参数如何定义?两者可以同时使用吗?
- 43. 剩余参数的类型如何定义?举例说明。
- 44. 什么是函数重载?如何在TypeScript中实现函数重载?重载的优先级规则是什么?
- 45. 箭头函数的类型定义与普通函数有区别吗?如何定义箭头函数的类型别名?
- 46. 函数的参数双向协变是什么?`strictFunctionTypes`配置项如何影响这一行为?
- 47. 如何定义一个“无返回值”的函数类型?`void`和`never`在此场景下的区别?
- 48. 如何用类型别名定义一个“接受任意参数、返回任意值”的函数类型?
- 49. 函数类型的兼容性规则是什么?参数数量、类型、返回值类型如何影响兼容性?
- 50. 如何给函数的`this`指定类型?举例说明。
- 二、100道TypeScript面试题目录列表
一、本文面试题目录
41. 如何在TypeScript中定义函数的参数类型和返回值类型?
-
答案:在TypeScript中,定义函数时可通过在参数后加
: 类型
指定参数类型,在函数体前加: 类型
指定返回值类型。若函数无返回值,返回值类型可指定为void
(默认会推断为void
)。 -
原理:通过显式类型声明,约束函数的输入和输出类型,确保调用时参数类型匹配,且返回值符合预期,避免类型不兼容导致的错误。
-
示例代码:
// 定义参数类型和返回值类型
function add(a: number, b: number): number {return a + b;
}// 无返回值函数(返回值类型为void)
function logMessage(message: string): void {console.log(message);
}// 函数表达式
const multiply = (x: number, y: number): number => x * y;// 错误示例(参数类型不匹配)
add("1", 2); // 报错:参数"1"应为number类型
42. 函数的可选参数和默认参数如何定义?两者可以同时使用吗?
-
答案:
- 可选参数:在参数名后加
?
,表示该参数可传可不传,格式为param?: 类型
。可选参数必须放在必选参数之后。 - 默认参数:通过
param: 类型 = 默认值
定义,若调用时未传该参数,将使用默认值。默认参数的类型可省略(由默认值推断)。
两者可以同时使用(可选参数+默认值),但通常默认参数已隐含“可选”特性,无需额外加
?
。 - 可选参数:在参数名后加
-
示例代码:
// 可选参数
function greet(name: string, title?: string): string {if (title) {return `Hello, ${title} ${name}`;}return `Hello, ${name}`;
}
greet("Alice"); // 允许(可选参数未传)
greet("Bob", "Mr"); // 允许// 默认参数
function calculateTotal(price: number, tax: number = 0.1): number {return price * (1 + tax);
}
calculateTotal(100); // 未传tax,使用默认值0.1 → 110
calculateTotal(100, 0.2); // 传tax,覆盖默认值 → 120// 可选参数+默认参数(不推荐,默认参数已隐含可选)
function formatText(text: string, prefix?: string = "Info:"): string {return `${prefix} ${text}`;
}
43. 剩余参数的类型如何定义?举例说明。
-
答案:剩余参数(通过
...
声明)用于接收函数的多个参数为数组,其类型需定义为数组类型(通常结合泛型或具体类型),格式为...rest: 类型[]
。 -
原理:剩余参数本质是将传入的多个参数打包为数组,因此类型需匹配数组的元素类型,确保所有剩余参数符合统一的类型约束。
-
示例代码:
// 剩余参数为number[]
function sum(...numbers: number[]): number {return numbers.reduce((total, num) => total + num, 0);
}
sum(1, 2, 3); // 6(参数均为number)
sum(10, 20, 30, 40); // 100// 剩余参数为string[]
function joinStrings(separator: string, ...parts: string[]): string {return parts.join(separator);
}
joinStrings("-", "2023", "10", "05"); // "2023-10-05"// 剩余参数结合联合类型
function logValues(...values: (string | number)[]): void {values.forEach(v => console.log(v));
}
logValues("a", 1, "b", 2); // 允许(混合string和number)
44. 什么是函数重载?如何在TypeScript中实现函数重载?重载的优先级规则是什么?
- 答案:函数重载是指为同一个函数定义多个不同的参数类型和返回值类型的签名,根据调用时的参数类型自动匹配对应的签名。
实现方式:
- 先定义多个函数重载签名(仅声明参数和返回值类型,无函数体);
- 最后定义一个实现签名(包含具体逻辑,需兼容所有重载签名)。
优先级规则:重载签名按定义顺序匹配,更具体的签名应放在前面,否则可能被更宽泛的签名优先匹配。
- 示例代码:
// 函数重载签名(多个)
function convert(value: string): number; // 字符串转数字
function convert(value: number): string; // 数字转字符串
function convert(value: boolean): string; // 布尔值转字符串// 实现签名(需兼容所有重载)
function convert(value: string | number | boolean): number | string {if (typeof value === "string") {return parseInt(value, 10);} else if (typeof value === "number") {return value.toString();} else {return value ? "true" : "false";}
}// 调用时匹配对应的重载
convert("123"); // 匹配第一个签名 → 返回number(123)
convert(456); // 匹配第二个签名 → 返回string("456")
convert(true); // 匹配第三个签名 → 返回string("true")
45. 箭头函数的类型定义与普通函数有区别吗?如何定义箭头函数的类型别名?
- 答案:箭头函数的类型定义与普通函数在类型约束逻辑上一致(均需指定参数类型和返回值类型),但语法形式不同:
- 普通函数:
function func(a: T): R {}
- 箭头函数:
const func = (a: T): R => {}
- 普通函数:
定义箭头函数的类型别名时,使用(参数: 类型) => 返回值类型
的格式,与普通函数类型别名一致。
- 示例代码:
// 箭头函数的类型定义
const add: (a: number, b: number) => number = (x, y) => x + y;// 用类型别名定义箭头函数类型
type MathOperation = (a: number, b: number) => number;
const subtract: MathOperation = (x, y) => x - y;
const multiply: MathOperation = (x, y) => x * y;// 带可选参数的箭头函数类型
type GreetFunc = (name: string, title?: string) => string;
const greet: GreetFunc = (name, title) => {return title ? `Hello, ${title} ${name}` : `Hello, ${name}`;
};
46. 函数的参数双向协变是什么?strictFunctionTypes
配置项如何影响这一行为?
- 答案:函数的参数双向协变指函数参数类型既支持协变(子类型→父类型)也支持逆变(父类型→子类型),即当函数
A
的参数类型是函数B
参数类型的父类型或子类型时,A
都可赋值给B
。
strictFunctionTypes
配置项的影响:
-
当
strictFunctionTypes: true
(严格模式):函数参数仅支持逆变(更严格),确保参数类型不被扩大,避免意外修改父类型的属性。 -
当
strictFunctionTypes: false
(默认):函数参数支持双向协变(更宽松),但可能导致类型不安全。 -
示例代码:
class Animal { name: string; }
class Dog extends Animal { breed: string; }// 函数类型:参数为Animal
type AnimalFunc = (a: Animal) => void;
// 函数类型:参数为Dog(Animal的子类型)
type DogFunc = (d: Dog) => void;const animalFunc: AnimalFunc = (a) => console.log(a.name);
const dogFunc: DogFunc = (d) => console.log(d.breed);// strictFunctionTypes: false(默认)→ 双向协变允许
const func1: AnimalFunc = dogFunc; // 允许(子类型参数→父类型参数)
const func2: DogFunc = animalFunc; // 允许(父类型参数→子类型参数)// strictFunctionTypes: true → 仅允许逆变
const func3: AnimalFunc = dogFunc; // 报错(不允许子类型参数→父类型参数)
const func4: DogFunc = animalFunc; // 允许(父类型参数→子类型参数,逆变)
47. 如何定义一个“无返回值”的函数类型?void
和never
在此场景下的区别?
- 答案:定义“无返回值”的函数类型时,返回值类型指定为
void
。
void
和never
的区别:
-
void
:表示函数正常执行完毕,但没有返回值(可隐式返回undefined
),适用于有明确结束点的函数(如仅执行副作用的函数)。 -
never
:表示函数永远不会执行完毕(如抛出异常、无限循环),适用于不会正常返回的函数。 -
示例代码:
// void类型:无返回值但正常结束
function log(message: string): void {console.log(message);// 隐式返回undefined,符合void
}// never类型:永远不返回
function throwError(message: string): never {throw new Error(message); // 抛出异常,函数中断
}function infiniteLoop(): never {while (true) {// 无限循环,永远不结束}
}// 错误示例(never函数不能有返回值)
function invalidNever(): never {return 123; // 报错:never类型函数不能返回值
}
48. 如何用类型别名定义一个“接受任意参数、返回任意值”的函数类型?
-
答案:通过
any
类型兼容任意参数和返回值,用类型别名定义为type AnyFunction = (...args: any[]) => any
。 -
原理:
...args: any[]
表示接收任意数量、任意类型的参数,=> any
表示返回任意类型的值,从而实现对函数输入输出的完全“无约束”。 -
示例代码:
// 定义接受任意参数、返回任意值的函数类型
type AnyFunction = (...args: any[]) => any;// 匹配该类型的函数示例
const func1: AnyFunction = () => "hello";
const func2: AnyFunction = (a: number, b: string) => a + b;
const func3: AnyFunction = (...args: boolean[]) => args.length;// 调用示例
func1(); // 允许
func2(10, "20"); // 允许(返回"1020")
func3(true, false); // 允许(返回2)
49. 函数类型的兼容性规则是什么?参数数量、类型、返回值类型如何影响兼容性?
- 答案:函数类型兼容性指一个函数能否赋值给另一个函数类型的变量,需满足以下规则:
-
参数数量:目标函数的参数数量可少于源函数(即源函数可多传参数,目标函数忽略多余参数)。
- 例:
(a: number) => void
可赋值给(a: number, b: number) => void
(错误); - 正确:
(a: number, b: number) => void
可赋值给(a: number) => void
(源函数参数更多)。
- 例:
-
参数类型:源函数的参数类型需与目标函数的参数类型兼容(通常为协变或逆变,受
strictFunctionTypes
影响)。 -
返回值类型:源函数的返回值类型需是目标函数返回值类型的子类型(协变)。
- 示例代码:
// 目标函数类型
type TargetFunc = (x: number) => string;// 1. 参数数量:源函数参数可多于目标函数
const sourceFunc1 = (x: number, y: number) => x.toString();
const func1: TargetFunc = sourceFunc1; // 允许(忽略y参数)// 2. 参数类型:源函数参数类型需兼容目标函数
type SourceFunc2 = (x: number) => string;
const func2: TargetFunc = sourceFunc2; // 允许(参数类型相同)// 3. 返回值类型:源函数返回值需是目标函数返回值的子类型
type SourceFunc3 = (x: number) => "a" | "b"; // "a"|"b"是string的子类型
const func3: TargetFunc = sourceFunc3; // 允许
50. 如何给函数的this
指定类型?举例说明。
-
答案:在函数的第一个参数位置,用
this: 类型
显式指定this
的类型(该参数仅用于类型声明,不影响实际调用)。 -
原理:TypeScript通过第一个参数的
this
类型约束函数执行时的上下文对象类型,确保函数内部使用的this
属性和方法符合预期。 -
示例代码:
// 定义对象类型
type User = {name: string;age: number;greet: () => void;
};// 给函数的this指定类型
function greet(this: User): void {console.log(`Hello, my name is ${this.name}, age ${this.age}`);
}// 正确使用(this指向User实例)
const user: User = {name: "Alice",age: 30,greet: greet // 绑定后,greet中的this为user
};
user.greet(); // 输出:Hello, my name is Alice, age 30// 错误示例(this类型不匹配)
const invalidThis = { name: "Bob" };
greet.call(invalidThis); // 报错:invalidThis缺少age属性,不符合User类型
二、100道TypeScript面试题目录列表
文章序号 | TypeScript面试题100道 |
---|---|
1 | TypeScript面试题及详细答案100道(01-10) |
2 | TypeScript面试题及详细答案100道(11-20) |
3 | TypeScript面试题及详细答案100道(21-30) |
4 | TypeScript面试题及详细答案100道(31-40) |
5 | TypeScript面试题及详细答案100道(41-50) |
6 | TypeScript面试题及详细答案100道(51-60) |
7 | TypeScript面试题及详细答案100道(61-70) |
8 | TypeScript面试题及详细答案100道(71-80) |
9 | TypeScript面试题及详细答案100道(81-90) |
10 | TypeScript面试题及详细答案100道(91-100) |