TypeScript中有哪些简单特性?

简介: TypeScript中有哪些简单特性?

类型与类型推断

当我们初学ts的时候,我们可能会写出这样的程序

let price: number = 123_456_789;//当数字太长,你可以使用下划线来分割以获取更好的阅读性
let item: string = "TypeSript";
let isNeed: boolean = true;

但实际上,ts编译器可以推断或者检测变量的类型

例如,我们已经将price初始化为一个数字,那么ts编译器将能够检测到这是一个numebr类型,这时候我们声明类型就是多余的了。

1.png

当我们声明了却没有初始化变量时,ts会将其推断为any类型(any类型表示所有类型,是所有类型的父类型,在ts中请尽量少的使用它)

2.png

这个时候我们可以给title赋不同类型的值,这并不是我们想看到的,所以我们应该在声明没有初始化的变量时,定义变量的类型

3.png

在我们声明函数时,我们可能不知道属性的类型具体是什么,这时候ts会给我们这个提示

4.png

这时候我们有两种选择:

1.将属性的类型显式声明为any。

2.ctrl+P搜索tsconfig.json文件,并找到"noImplicitAny": true,将其去掉注释并改为false(不建议,除非有大量的错误,但那样你可能会失去使用ts的意义)

Array

同样的,如果我们声明一个空数组

const arr = [];//它的类型为any[]

由前面的经验,我们明白,我们应该给arr声明类型

const arr: number[] = [];//类型为number[]

ts有一个特性:在使用某个确定类型的变量时,你能够得到相应类型方法的代码补全提示。

这也是我们为什么使用ts的一个重要原因

5.png

Tuples/元组

ts有一个名为Tuples/元组的新类型,这是一个拥有固定长度的数组,并且每个元素都有一个特定的类型。我们经常会在处理一对值时使用它。

let user: [number, string] = [20, "kevin"];//类型为[number, string] 注意,这里的类型与元素的位置是对应的
//let user: [number, string] = ["kevin", 20]; //错误:不能将类型“string”分配给类型“number”。

同时,当我们声明第三个元素时,将会报错,因为元组的元素长度是固定的。

let user: [number, string] = [20, "kevin", 0];
//错误:不能将类型“[number, string, number]”分配给类型“[number, string]”。源具有 3 个元素,但目标仅允许 2 个。ts(2322)

关于元组,你应该知道的是:在内部,使用的是普通的js数组,如果我们编译代码,那么得到的只是一个普通的js数组:

"use strict";
let user = [20, "kevin"];
//# sourceMappingURL=demo.js.map

关于元组,有一个需要注意的是,虽然元组是固定长度的数组,但你仍然可以使用push添加元素。这也许是一个漏洞,希望将来会得到解决。

let user: [number, string] = [20, "kevin"];
user.push("demo");//只要类型为 number|string 并不会报错

关于元组的最佳实践:当数组只有两个值的时候可以使用(如键值对),但当你有更多的元素,使用元组可能让你的代码的阅读性更差。

Enum/枚举

枚举与数组类似,在以前我们定义三个常量可能会这样做:

const small = 1;
const medium = 2;
const large = 3;

不过在ts中,我们可以使用枚举:

enum SizeList {
  Small,//默认为0
  Medium,//后面的值依次增长
  Large,
}

当然,你可以显式的设置值

enum SizeList {
  Small = 1,//定义为1
  Medium,//值为2,以此类推
  Large,
}

或者将值声明为其他类型,不过这时候,你需要声明每个常量的值:

enum SizeList {
  Small = "s",
  Medium = "m",
  Large = "l",
}

使用枚举:

enum SizeList {
  Small = 1,
  Medium,
  Large,
}
let mySize: SizeList = SizeList.Medium;
console.log(mySize);//2

我们看到编译后的js文件,代码似乎有些长:

"use strict";
var SizeList;
(function (SizeList) {
    SizeList[SizeList["Small"] = 1] = "Small";
    SizeList[SizeList["Medium"] = 2] = "Medium";
    SizeList[SizeList["Large"] = 3] = "Large";
})(SizeList || (SizeList = {}));
let mySize = SizeList.Medium;
console.log(mySize);
//# sourceMappingURL=demo.js.map

我们可以通过一个小技巧,让ts编译器生成更加优化的代码:在enum前添加const

const enum SizeList {
  Small = 1,
  Medium,
  Large,
}
let mySize: SizeList = SizeList.Medium;
console.log(mySize);

下面是编译后的js文件:

"use strict";
let mySize = 2;
console.log(mySize);
//# sourceMappingURL=demo.js.map

总结:我们可以通过枚举表示相关常量的列表,如果我们const声明enum,编译器将生成更加优化的代码。

function

在声明函数时,根据最佳实践,我们应该对函数的属性和返回值的类型进行声明:

function taxation(income: number) {}//它的类型为function taxation(income: number): void
//我们应该这样做:
function taxation(income: number): number {
  return 0;
}//它的类型为function taxation(income: number): number

对于上面的函数,我们并没有在函数中使用到传入的参数,我们希望ts能够给我们警告,我们可以在tsconfig.json中配置它:

找到"noUnusedParameters": true,并打开它

6.png

这时候我们就得到一个警告了

我们写这个函数:

function taxation(income: number): number {
  if (income < 50_000) return income * 1.2;
}//函数缺少结束 return 语句,返回类型不包括 "undefined"。

出现这个报错的原因是,只有在符合条件时才会返回income*1.2,而不符合则返回undefined(在js中,未赋值的变量都为undefined),而undefined不为number类型。

我们可以去除函数的返回值类型

function taxation(income: number) {
  if (income < 50_000) return income * 1.2;
}//function taxation(income: number): number | undefined

这样不会报错,但这样并不符合ts的使用标准,我们不希望会返回undefined,我们希望我们这样做的时候ts对我们进行警告

我们可以在tsconfig.json中找到"noImplicitReturns": true,并打开它。

这样,你就得到想要的警告了。

7.png

对于上面的函数,我们应该这样写:

function taxation(income: number): number {
  if (income < 50_000) return income * 1.2;
  return income * 1.3;
}

在函数中,我们可能声明了变量/常量却没有使用,我们同样希望得到提示:

function taxation(income: number): number {
  let a = 1;
  if (income < 50_000) return income * 1.2;
  return income * 1.3;
}

我们可以在tsconfig.json中找到"noUnusedLocals": true,并打开它。

这时候我们将得到一个提示:已声明“a”,但从未读取其值。ts(6133)

现在我们的函数有两个参数,但我们在调用的时候传入了三个,这时候ts会给我们报错,而在js中并不会报错

function taxation(income: number, taxYear: number): number {
  if (taxYear < 2022) return income * 1.2;
  return income * 1.3;
}
​
taxation(300_000, 2023, 1);//报错:应有 2 个参数,但获得 3 个。ts(2554)

我们可能会想让taxYear属性为可选属性,我们可以在冒号前使用来声明可选属性。

但通常情况下,ts会给我们报错:

function taxation(income: number, taxYear?: number): number {
  if (taxYear < 2022) return income * 1.2;
  return income * 1.3;
}//对象可能为“未定义”。ts(2532)

因为如果我们没有传入taxYear,那么taxYear在函数中就为undefined,但undefined转换为数字后为NAN。并不能进行比较

对此,我们有两个解决方法:

1.旧版写法(不推荐):

function taxation(income: number, taxYear?: number): number {
  if ((taxYear || 2022) < 2022) return income * 1.2;
  return income * 1.3;
}

2.es6写法(推荐):

function taxation(income: number, taxYear = 2023): number {
  if (taxYear < 2022) return income * 1.2;
  return income * 1.3;
}
​
taxation(300_000, 2024);//taxYear的默认值为2023,调用时传入2024,将会覆盖掉默认值

总结:作为最佳实践,我们应该始终正确的注释函数,参数类型,返回值类型。并且启用tsconfig.json中的

"noUnusedParameters": true,(没有未使用的参数),"noUnusedLocals": true,(没有未使用的变量),"noImplicitReturns": true,(没有隐式返回)

Object

当我们像js那样使用对象时,ts会给我们报错

let man = { age: 22 };
man.name = "kevin";//报错:类型“{ age: number; }”上不存在属性“name”。ts(2339)

在ts中使用对象时,我们也应该像function那样,明确的声明对象的类型:

let man:{
    name:string,
    age:number
} =  { age: 22 };//类型 "{ age: number; }" 中缺少属性 "name",但类型 "{ name: string; age: number; }" 中需要该属性。ts(2741)
man.name = "kevin";

这时候同样会报错,因为我们在声明对象时没有对对象的属性进行声明。也就是没有声明name属性。

我们可以使用ts的特性,让其属性为可选属性

let man: {
  name?: string;
  age: number;
} = { age: 22 };
man.name = "kevin";

但是,我们不应该这样使用。

我们不能盲目地使用ts的特性。我们在写代码的同时,也应该考虑代码的合理性,毕竟没有一个man的name为undefined

所以,我们还是应该这样使用:

let man: {
  name: string;
  age: number;
} = { age: 22, name: "kevin" };

只读属性

在声明对象时,我们可能希望某些属性不被更改。对此,我们可以使用readonly关键字,它表示(只读的)

let man: {
  readonly name: string;
  age: number;
} = { age: 22, name: "kevin" };
man.name = "qian";//无法分配到 "name" ,因为它是只读属性。ts(2540)

对象的方法

在声明方法时,我们同样的要给函数声明函数签名(也叫类型签名,或方法签名,定义了函数或方法的输入与输出)

let man: {
  readonly name: string;
  age: number;
  retire: (date: Date) => void;//函数签名
} = {
  age: 22,
  name: "kevin",
  retire: (date: Date) => {
    console.log(date);
  },
};
相关文章
|
4月前
|
存储 JavaScript 安全
TypeScript 中的 Number 类型,Number 类型的特性、常见操作和注意事项
TypeScript 中的 Number 类型,Number 类型的特性、常见操作和注意事项
399 1
|
4月前
|
JavaScript
TypeScript 类的特性、使用方法以及注意事项
TypeScript 类的特性、使用方法以及注意事项
61 0
|
4月前
|
JavaScript 前端开发 开发者
深入理解ArkTS:Harmony OS 应用开发语言 TypeScript 的基础语法和关键特性
深入理解ArkTS:Harmony OS 应用开发语言 TypeScript 的基础语法和关键特性
522 0
|
3月前
|
前端开发 JavaScript 安全
TypeScript作为一种静态类型的JavaScript超集,其强大的类型系统和面向对象编程特性为微前端架构的实现提供了有力的支持
【6月更文挑战第11天】微前端架构借助TypeScript提升开发效率和代码可靠性。 TypeScript提供类型安全,防止微前端间通信出错;智能提示和自动补全加速跨代码库开发;重构支持简化代码更新。通过定义公共接口确保一致性,用TypeScript编写微前端以保证质量。集成到构建流程确保顺利构建打包。在微前端场景中,TypeScript是强有力的语言选择。
42 2
|
4月前
|
存储 JavaScript 索引
TypeScript 中的元组类型:元组的特性、常见操作和注意事项
TypeScript 中的元组类型:元组的特性、常见操作和注意事项
203 1
|
4月前
|
JavaScript 安全 前端开发
【亮剑】TypeScript 由于其强类型的特性,直接为对象动态添加属性可能会遇到一些问题
【4月更文挑战第30天】本文探讨了在 TypeScript 中安全地为对象动态添加属性的方法。基础方法是使用索引签名,允许接受任何属性名但牺牲了部分类型检查。进阶方法是接口扩展,通过声明合并动态添加属性,保持类型安全但可能导致代码重复。高级方法利用 OOP 模式的类继承,确保类型安全但增加代码复杂性。选择哪种方法取决于应用场景、代码复杂性和类型安全性需求。
47 0
|
4月前
|
JavaScript 前端开发 安全
详细介绍 TypeScript 函数的各种特性、用法和最佳实践
详细介绍 TypeScript 函数的各种特性、用法和最佳实践
71 3
|
JavaScript
TypeScript 4.1 新特性:字符串模板类型,Vuex 终于有救了?
TypeScript 4.1 快要发布了,老爷子 Anders Hejlsberg[1] 加入了一项重大更新,「字符串模板类型」 的支持。昨天看到这个更新的我特别兴奋,曾几何时,只要一遇到字符串拼接相关的类型,TypeScript 就束手无策了
|
存储 JavaScript 前端开发
TypeScript语言特性(上)
TypeScript是一个开源的、跨平台且带有类型系统的JavaScript超集,它可以编译为纯JavaScript,然后运行在任意的浏览器和其他环境中。它使开发者可以使用一些未来JavaScript标准(ECMAScript 6和7)中的特性。TypeScript为JavaScript添加了可选的
5441 0
|
2月前
|
前端开发 JavaScript 安全
TypeScript在React Hooks中的应用:提升React开发的类型安全与可维护性
【7月更文挑战第17天】TypeScript在React Hooks中的应用极大地提升了React应用的类型安全性和可维护性。通过为状态、依赖项和自定义Hooks指定明确的类型,开发者可以编写更加健壮、易于理解和维护的代码。随着React和TypeScript的不断发展,结合两者的优势将成为构建现代Web应用的标准做法。