- Hands-On Functional Programming with TypeScript
- Remo H. Jansen
- 625字
- 2021-07-02 14:03:10
side-effects
In the preceding section, we learned that a pure function returns a value that can be computed using only the arguments passed to it. A pure function also avoids mutating its arguments or any other external variable that is not passed to the function as an argument. In FP terminology, it is common to say that a pure function is a function that has no side-effects, which means that, when we invoke a pure function, we can expect that the function is not going to interfere (through a state mutation) with any other component in our application.
Certain programming languages, such as Haskell, can ensure that an application is free of side-effects using their type system. TypeScript has fantastic interoperability with JavaScript, but the downside of this, compared to a more isolated language such as Haskell, is that the type system is not able to guarantee that our application is free from side-effects. However, we can use some FP techniques to improve the type safety of our TypeScript applications. Let's take a look at an example:
interface User {
ageInMonths: number;
name: string;
}
function findUserAgeByName(users: User[], name: string): number {
if (users.length == 0) {
throw new Error("There are no users!");
}
const user = users.find(u => u.name === name);
if (!user) {
throw new Error("User not found!");
} else {
return user.ageInMonths;
}
}
The preceding function returns a number. The code compiles without issues. The problem is that the function does not always return a number. As a result, we can consume the function as follows and our code will compile and throw an exception at runtime:
const users = [
{ ageInMonths: 1, name: "Remo" },
{ ageInMonths: 2, name: "Leo" }
];
// The variable userAge1 is as number
const userAge1 = findUserAgeByName(users, "Remo");
console.log('Remo is ${userAge1 / 12} years old!');
// The variable userAge2 is a number but the function throws!
const userAge2 = findUserAgeByName([], "Leo"); // Error
console.log('Leo is ${userAge2 / 12} years old!');
The following example showcases a new implementation of the preceding function. This time, instead of returning a number, we will explicitly return a promise. The promise forces us to then use the handler. This handler is only executed if the promise is fulfilled, which means that if the function returns an error, we will never try to convert the age to years:
function safeFindUserAgeByName(users: User[], name: string): Promise<number> {
if (users.length == 0) {
return Promise.reject(new Error("There are no users!"));
}
const user = users.find(u => u.name === name);
if (!user) {
return Promise.reject(new Error("User not found!"));
} else {
return Promise.resolve(user.ageInMonths);
}
}
safeFindUserAgeByName(users, "Remo")
.then(userAge1 => console.log('Remo is ${userAge1 / 12} years old!'));
safeFindUserAgeByName([], "Leo") // Error
.then(userAge1 => console.log('Leo is ${userAge1 / 12} years old!'));
The Promise type helps us to prevent errors because it expresses potential errors in an explicit way. In programming languages such as Haskell, this is the default behavior of the type system, but, in programming languages such as TypeScript, it is up to us to use types in a safer way.
- Microsoft Exchange Server PowerShell Cookbook(Third Edition)
- Git Version Control Cookbook
- 薛定宇教授大講堂(卷Ⅳ):MATLAB最優(yōu)化計算
- Hands-On Microservices with Kotlin
- 零基礎(chǔ)輕松學(xué)C++:青少年趣味編程(全彩版)
- INSTANT Apache ServiceMix How-to
- Python 快速入門(第3版)
- 軟件再工程:優(yōu)化現(xiàn)有軟件系統(tǒng)的方法與最佳實踐
- LibGDX Game Development By Example
- C++從零開始學(xué)(視頻教學(xué)版)(第2版)
- Qt編程快速入門
- jQuery基礎(chǔ)教程(第4版)
- Java程序設(shè)計基礎(chǔ)教程
- Unity Certified Programmer:Exam Guide
- 軟件測試實用教程