前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【TypeScript】超详细的笔记式教程【中】

【TypeScript】超详细的笔记式教程【中】

作者头像
HoMeTown
发布2022-10-26 08:32:03
1K0
发布2022-10-26 08:32:03
举报
文章被收录于专栏:秃头开发头秃了

数组

基本定义

在TypeScript中,数组的定义如下:

代码语言:javascript
复制
let fibonacci: number[] = [1,2,3,4,5]

上面的🌰中,不允许出现除number以外的类型,比如:

代码语言:javascript
复制
let fibonacci: number[] = [1,2,3, true]

这样写会抛出异常不能将类型“(number | boolean)[]”分配给类型“number”

数组的方法也会根据数组在定义时的类型约定,受到限制,举个🌰

代码语言:javascript
复制
let fibonacci: number = [1,2,3,4]
fibonacce.push(true)

这样写也不行,会抛出错误不能将类型“number[]”分配给类型“number” && 不能将类型“number[]”分配给类型“number”

接口表示

举个🌰

代码语言:javascript
复制
interface NumberArray {
    [index: number]: number;
}
let fibonacce: NumberArray = [1,2,3,4]

NumberArray:索引是数字时,值的类型必须用数字。

一般不会用这个去定义一个数组。

类数组

类数组不能用数组定义的方式去赋值,举个🌰

代码语言:javascript
复制
function sum() {
    let args: number[] = arguments;
}

这样写会抛出错误类型“IArguments”缺少类型“number[]”的以下属性: pop, push, concat, join 及其他 24 项

因为类数组并没有数组原型上的方法,pop等等,所以如果用array去定义,那么类型校验不通过,我们可以用IArguments类型去定义一个类数组,举个🌰:

代码语言:javascript
复制
function sum() {
    let agrs: IArguments = arguments;
}

类型IArguments其实就是一个interface,是TypeScript内置的类型,相当于这样写:

代码语言:javascript
复制
interface IAgruments {
    [index: number]: any;
    length: number;
    callee: function;
}

除此之外,TypeScript中还有很多内置的类型,比如NodeListHTMLCollection

数组 any

无限制的数组项,举个🌰

代码语言:javascript
复制
let list: any[] = [1, '1', true, {name: '1'}, [3,4,5]]

完全ok!

函数

基本定义

TypeScript中函数的定义如下:

代码语言:javascript
复制
function sum(x: number, y: number): number {
    return x + y
}

函数表达式

代码语言:javascript
复制
let sum = function(x: number, y: nunmber): number {
    return x + y
}

sum并没有类型的定义,可以给sum也加一个定义:

代码语言:javascript
复制
let sum: (x: number, y: number) => number = function(x: number, y: number): number {
    return x + y
}

上面所有的定义中,函数的参数都是必传的,不能少,也不能多,比如这样:

再比如,这样:

可选参数

与接口中的可选属性类似,用?表示,举个🌰:

代码语言:javascript
复制
let buildName: (f: string, l?: string) => string = function (
  firstName: string,
  lastName?: string
): string {
  if (lastName) return firstName + " " + lastName;
  return firstName;
};

console.log(buildName("Alice"));
console.log(buildName("Alice", "Yan"));

需要注意的是,可选参数必须在最后面,也就是说,可选参数的后面,不能再接必需参数,像这样就不行:

参数默认值

TypeScript会将添加了默认值的参数自动设置为可选参数,举个🌰

代码语言:javascript
复制
function buildName(firstName: string, lastName: string = 'Yan'): string {
    return firstName + ' ' + lastName
}
console.log(buildName('Alice'))

此时就不受「可选参数必须在必须参数后面」的限制了

剩余参数

...rest获取剩余参数

代码语言:javascript
复制
function push(array: any[], ...items: any[]) {
    items.forEach( item => array.push(item))
}

类型断言

用于手动指定一个值的类型

基本语法

(推荐)

代码语言:javascript
复制
值 as 类型

or

(不推荐)

代码语言:javascript
复制
<类型> 值

用途

将一个联合类型断言为其中一个类型

TypeScript不确定一个联合类型的变量到底属于哪个类型的时候,只能访问此联合类型的所有类型中共有的属性或方法,比如之前说的string | number 访问toString,再举个栗子:

代码语言:javascript
复制
interface Dog {
    name: string;
    run(): void;
}

interface Fish {
    name: string;
    swim(): void;
}

function getName(animal: Dog | Fish) {
    return animal.name
}

有时候,我们确实需要在还不确定类型的时候就访问其中一个类型特有的属性或方法,举个栗子:

代码语言:javascript
复制
interface Dog {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}
function isFish(animal: Dog | Fish) {
    if( typeof animal.swim === 'function' ) return true
    return false
}

上面这个栗子就会抛出错误类型“Dog | Fish”上不存在属性“swim”

这个时候我们就可以用类型断言,将animal断言成Fish

代码语言:javascript
复制
interface Dog {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}

function isFish(animal: Dog | Fish): boolean {
    if(typeof (animal as Fish).swim === 'function') return true
    return false
}

📢注意:类型断言只能够【欺骗】TypeScript编译器,无法避免运行时的错误,滥用类型断言可能会导致运行错误,举个栗子:

代码语言:javascript
复制
interface Dog {
    name: string;
    run(): void;
}
interface Fish {
    name: string;
    swim(): void;
}
function goSwim(animal: Dog | Fish): void {
    (animal as Fish).swim()
}
const tony: Dog = {
    name: 'Tony',
    run() { console.log('im run!')}
}

swim(tony)

将一个父类断言为更加具体的子类

当类之间有继承关系时,类型断言也是很常见,举个栗子:

代码语言:javascript
复制
class ApiError extends Error {
    code: number = 0;
}

class HttpError extends Error {
    statusCode: number = 200;
}

function isApiError(error: Error) {
    if( typeof (error as ApiError).code === 'number') return true
    return false
}

这个栗子中,声明了函数`isApiError`,用来判断传入的参数是不是`ApiError`类,但是由于父类`Error`中并没有`code`这个属性,所以直接使用就会报错,就要使用`as`进行`类型断言`

将任何一个类型断言为any

这其实就是有一点不靠谱了,咱就是整个就是说你定义一个类型是number,但是如果你又觉得他好像不是number,那你可以把他再断言成any,举个栗子:

代码语言:javascript
复制
const foo: number = 1
foo.length = 1

这样写是不能通过编译的,因为foonumber类型,是没有length属性的,所以TypeScript给了提示类型“number”上不存在属性“length”。,这种提示非常有效!

但是有时候我们的写法是完全没有问题的,比如:

代码语言:javascript
复制
window.foo = 1

在js中,这种写法完全ok,给window添加属性foo,值为1,但是,在TypeScript中是不支持的,它会抛出这个错误类型“Window & typeof globalThis”上不存在属性“foo”。,这时候我们就可以用类型断言,把window断言成anyany类型上,访问任何属性都是允许的,像这样:

代码语言:javascript
复制
(window as any).foo = 1

ok

将any断言成任何一种类型

举个栗子:

代码语言:javascript
复制
function getCacheData(key: string): any {
    return (window as any).cache[key]
}

上面的例子中,getCacheData返回的类型是any,我们不确定他到底返回的是什么类型,所以当我们使用这个function的时候,我们可以根据自己的需要,对他的返回值进行断言,举个栗子:

代码语言:javascript
复制
interface Cat {
    name: string;
    run(): void;
}
const tom = getCacheData('tom') as Cat;
tom.run()

断言包含

并不是所有的类型都能够相互断言,只有A包含B的所有属性,或者B包含A的所有属性,AB才能相互断言,举个栗子:

代码语言:javascript
复制
interface Animal {
  name: string;
}

interface Cat {
  name: string;
  run(): void;
}

let tom: Cat = {
  name: "tom",
  run() {
    console.log("i can run");
  },
};

let anmimal: Animal = tom;
tom.run();
(anmimal as Cat).run();

如果我们加一个新的interface:

代码语言:javascript
复制
let coffeeCup: Cup = {
  width: 20,
  height: 60,
};

let anmimalCup: Animal = coffeeCup;

就会抛出错误类型 "Cup" 中缺少属性 "name",但类型 "Animal" 中需要该属性。

总结

类型断言的用途:

  • 联合类型可以断言为其中一个类型
  • 父类可以被断言为自类
  • 任何类型可以断言成 any
  • any可以断言成任何类型
  • A包含B的所有属性,或者B包含A的所有属性,AB才能相互断言

双重断言

双重断言意味着打破 「A包含B的所有属性,或者B包含A的所有属性,AB才能相互断言」的规则,举个栗子:

代码语言:javascript
复制
interface Cat {
  run(): void;
}
interface Fish {
  siwm(): void;
}

function testCat(cat: Cat) {
  return cat as any as Fish;
}

let tom: Cat = {
  run() {
    console.log("i can run");
  },
};

testCat(tom);

声明

declare var

声明全局变量

代码语言:javascript
复制
declare var username: string;

declare function

定义全局函数

代码语言:javascript
复制
declare function getToken(key: string): string
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 秃头开发头秃了 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 数组
    • 基本定义
      • 接口表示
        • 类数组
          • 数组 any
          • 函数
            • 基本定义
              • 函数表达式
                • 可选参数
                  • 参数默认值
                    • 剩余参数
                    • 类型断言
                      • 基本语法
                        • 用途
                          • 将一个联合类型断言为其中一个类型
                          • 将一个父类断言为更加具体的子类
                          • 将任何一个类型断言为any
                          • 将any断言成任何一种类型
                          • 断言包含
                        • 总结
                          • 双重断言
                          • 声明
                            • declare var
                              • declare function
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档