TypeScript 为 JavaScript 带来了什么
TypeError 举例,TS 是如何解决的
当一项新技术摆在我这样的懒人前,有必要弄清学它的必要性,否则一定会半途而废。JavaScript 的过于灵活,一直以来为人诟病。它所带来的麻烦,主要体现在很多 TypeError 报错,直到运行时才会暴露出来。这一点在我的编程体验中最为深刻。以下是 chatgpt 对这个问题的理解和 typescript 能在多大程度上解决这类错误。
You:
JavaScript 中的 TypeError
ChatGPT:
在 JavaScript 中,TypeError 是一种常见的错误类型,当尝试对一个数据类型执行不适合的操作时会抛出。下面是一些常见的 TypeError 发生的情况:
- 访问未定义的属性 :
let obj;
console.log(obj.property); // TypeError: Cannot read property 'property' of undefined
- 调用非函数类型的变量 :
let nonFunction = 123;
nonFunction(); // TypeError: nonFunction is not a function
- 将值赋给只读属性 :
const obj = {};
Object.defineProperty(obj, "prop", {
value: 42,
writable: false,
});
obj.prop = 77; // TypeError: Cannot assign to read only property 'prop' of object
- 在基础数据类型上调用方法 :
null.someMethod(); // TypeError: Cannot read property 'someMethod' of null
- 使用
new
关键字调用不是构造函数的对象 :
let notAConstructor = {};
new notAConstructor(); // TypeError: notAConstructor is not a constructor
为了处理这些错误,可以使用 try...catch
语句来捕获和处理异常。例如:
try {
let obj;
console.log(obj.property);
} catch (e) {
if (e instanceof TypeError) {
console.error("TypeError caught:", e.message);
} else {
throw e;
}
}
通过合理的错误处理,可以使代码更加健壮,并能够更好地调 试和维护。
You:
这些错误能通过把 js 改写为 typescript 来解决吗
ChatGPT:
将 JavaScript 转换为 TypeScript 可以预防许多类型相关的错误,因为 TypeScript 提供了静态类型检查和更严格的语法规则。然而,TypeScript 并不能完全消除所有运行时错误。让我们看看上述几种 TypeError 是如何在 TypeScript 中得到改进或预防的:
- 访问未定义的属性 :
let obj: { property?: string };
console.log(obj.property); // TypeScript 提示 obj 可能为 undefined
TypeScript 会警告你 obj
可能是 undefined
,需要检查或使用类型保护。
- 调用非函数类型的变量 :
let nonFunction: any = 123;
(nonFunction as Function)(); // TypeScript 会警告类型不匹配
TypeScript 类型系统会阻止非函数类型的变量被调用。
- 将值赋给只读属性 :
interface MyObject {
readonly prop: number;
}
const obj: MyObject = { prop: 42 };
obj.prop = 77; // TypeScript 编译错误: Cannot assign to 'prop' because it is a read-only property.
TypeScript 通过 readonly
修饰符强制只读属性不可被重新赋值。
- 在基础数据类型上调用方法 :
let nullable: null | { someMethod: () => void } = null;
nullable.someMethod(); // TypeScript 提示 nullable 可能为 null
TypeScript 会提示 nullable
可能是 null
,需要进行检查。
- 使用
new
关键字调用不是构造函数的对象 :
let notAConstructor: any = {};
new notAConstructor(); // TypeScript 编译错误: Cannot use 'new' with an expression whose type lacks a call or construct signature.
TypeScript 会阻止在非构造函数的对象上使用 new
关键字。
TypeScript 通过静态类型检查、接口、类型断言等机制,大大减少了因为类型错误而导致的运行时异常。尽管如此,TypeScript 不能完全避免所有错误,特别是那些涉及到动态数据和外部输入的错误,因此在编写 TypeScript 代码时仍需谨慎,并结合适当的错误处理机制。
TS 很强,但是还不够
TypeScript 类型检查的范围只局限在代码编译阶段,运行时是无能为力的。比如一次数据库查询期望返回一个数组格式的数据,但是因为某种原因变成了 undefined,那么后续代码用到这个数组的地方就会报错了。所以,涉及到动态数据的,应该要手动加类型检查,比如说
if (!Array.isArray(o)) {
throw new Error();
}
强类型?弱类型?
ts 是在 js 的基础上加上了类型,因此成了一门静态语言。但是,这种静态类型还要加一个"弱"的形容词。这是因为,ts 和 js 一样会执行隐式转换而不会报错。
console.log(1 + "1");
// 打印出字符串 '11'
上面这段代码,js/ts 都能执行成功。