age = ‘余光’
// 不能将类型“string”分配给类型“number”
// Type ‘string’ is not assignable to type ‘number’.
类型检测会提前帮我们规避一些不必要的风险,大家在平时也一定会遇到类型不匹配这样的错误,如果是any
类型,则允许被赋值为任意类型。但写多了any和Js就没“区别”了不是吗?
let age:any = 100;
age = ‘余光’;
3.1 任意值的属性和方法
-
在任意值上访问任何属性都是允许的;
-
调用任意方法也是允许的;
let anyThing: any = ‘todo’;
console.log(anyThing.myName);
console.log(anyThing.myName.firstName);
anyThing.toString();
可以认为,声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值。
3.2 未声明类型的变量在未指定其类型时会被识别为any
变量如果在声明的时候,未指定其类型,那么它会被识别为任意值类型:
let something;
something = ‘str’;
something = 7;
something.name = ‘余光’;
// 等价于
let something: any;
something = ‘str’;
something = 7;
something.name = ‘余光’;
注意:
经过前面两点(尤其是第二点)的描述,你会发现如果给变量添加了any
的声明,那么Typescript就变成了AnyScript了,那岂不是一夜回到了解放前?理论上我们尽量不使用any,就好像才出现了const和let之后,我们进来避免试用var一样。
在TypeScript中,数组类型有多种定义方式声明一个类似于 [1, 2, 3] 的数组类型,你可以用number[]
。这个语法可以适用于任何类型(举个例子,string[] 表示一个字符串数组)。你也可能看到这种写法 Array<number>
,是一样的。未来了解泛型时我们再来深入的研究。先来了解一下简单方法吧~
4.1 类型 + 方括号
let fibonacci: number[] = [1, 1, 2, 3, 5]; // 此时数组内每个元素都会进行类型检测
fibonacci.push(‘8’); // 类型“string”的参数不能赋给类型“number”的参数。
4.2 数组泛型
具体详细内容我们之后再展开~
我们可以使用数组泛型(Array Generic) Array<elemType>
来表示数组:
let fibonacci: Array = [1, 1, 2, 3, 5];
4.3 any在数组中的应用
一个比较常见的做法是,用 any 表示数组中允许出现任意类型:
let list: any[] = [‘xcatliu’, 25, { website: ‘http://xcatliu.com’ }];
对于any约束的数字,其实就是主动放弃了类型检测~
除了原始类型,最常见的类型就是对象类型了。定义一个对象类型,我们只需要简单的列出它的属性和对应的类型。
5.1 对象属性注释
来看下面一段代码:
**注意:**此时参数的数量不一致,会导致报错,其实这是因为它们的形状不同,之后我们会展开来说~
function getName(obj: { name: string; age: number }): void {
console.log(obj.name);
console.log(obj.age);
}
const res = getName({ name: “余光”, age: 100 });
// ✅
const res2 = getName({ name: “余光”, age: 100 });
// ❌ 类型 “{ name: string; }” 中缺少属性 “age”,但类型 “{ name: string; age: number; }” 中需要该属性。
不难理解,我们将参数 obj 内部的属性进行了类型注释,并在之后检查对应的类型。
5.2 可选属性
对象类型可以指定一些甚至所有的属性为可选的,你只需要在属性名后添加一个 ?:
function getName(obj: { name: string; age?: number }): void {
console.log(obj.name);
console.log(obj.age);
}
getName({ name: “余光” });
注意可选属性可以不存在,但仍然不允许添加未定义的属性。
在JavaScript中,如果你获取一个不存在的属性,你会得到一个undefined
而不是一个运行时错误。因此,当你获取一个可选属性时,你需要在使用它前,先检查一下是否是undefined
。
function getName(obj: { name: string; age?: number }): void {
console.log(obj.name);
console.log(obj.age);
}
getName({ name: “余光” });
// 余光
// undefined
在函数是JavaScript中是一等公民,在Ts中,它允许我们指定输入类型和输出类型。
6.1 参数类型注解(Parameter Type Annotations)
当你声明一个函数的时候,你可以在每个参数后面添加一个类型注解,声明函数可以接受什么类型的参数。参数类型注解跟在参数名字后面:
函数声明:
function sum(x: number, y: number): number {
return x + y;
}
// 输入多余的(或者少于要求的)参数,是不被允许的:
sum(1);
// 应有 2 个参数,但获得 1 个。ts(2554)
sum(1, 2, 3);
// 应有 2 个参数,但获得 3 个
6.2 可选参数和参数默认值
前面提到,输入多余的(或者少于要求的)参数,是不允许的。那么如何定义可选的参数呢?与接口中的可选属性类似,我们用?
表示可选的参数:
注意:可选参数必须接在必需参数后面。换句话说,可选参数后面不允许再出现必需参数了。
function hello(name1: string, name2?: string): void {
console.log(hello! ${name1} ${name2 ? "and" + " " + name2 : ""}
);
}
hello(“余光1”, “余光2”); // hello! 余光1 and 余光2
hello(“余光”); // hello! 余光
同样添加默认值也是可以的,TypeScript 会将添加了默认值的参数识别为可选参数:
function hello(name1: string = “余光”, name2: string = “yuguang”): void {
console.log(hello! ${name1} ${name2 ? "and" + " " + name2 : ""}
);
}
hello(); // hello! 余光 and yuguang
hello(“小明”); // hello! 小明 and yuguang
6.3 匿名函数
匿名函数有一点不同于函数声明,当 TypeScript 知道一个匿名函数将被怎样调用的时候,匿名函数的参数会被自动的指定类型。
这个例子来自“冴羽大佬”的示例👍
const arr = [1, 2, 3, 4];
arr.forEach((val) => {
val.toFixed(1);
});
// ✅
arr.forEach((val) => {
val.split(“-”);
});
// ❌ 类型“number”上不存在属性“split”。
尽管参数val
并没有添加类型注解,但TypeScript根据forEach函数的类型,以及传入的数据的类型,最后推断出了val
的类型。
这个过程被称为上下文推断(contextual typing),因为正是从函数出现的上下文中推断出了它应该有的类型。
联合类型(Union Types)表示取值可以为多种类型中的一种。
7.1 定义一个联合类型
前面我们提到了基本类型是怎么指定的,如果你希望一个变量的类型是可选的可以使用any,但还有更好的方式——是明确指定几个类型——联合类型
let category: string | number;
category = ‘余光’;
category = 7;
category = true; // ❌ 不能将类型“boolean”分配给类型“string | number”。
联合类型使用 |
分隔每个类型。表示允许设置的类型,这其中每个类型都是联合类型的成员(members)。
注意
当TypeScript不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
function getLength(something: string | number[]): number {
return something.length;
}
// ✅
function getLength(something: string | number): number {
return something.length;
}
// ❌ 类型“string | number”上不存在属性“length”。类型“number”上不存在属性“length”。
联合类型的变量在被赋值的时候,会根据类型推论的规则推断出一个类型,所以也会遇到上面问题
let val: string | number;
val = ‘seven’;
console.log(val.length); // 5
val = 7;
console.log(val.length); // ❌ 类型“number”上不存在属性“length”
类型别名用来给一个类型起个“新”名字。例如:
type hasLen = string | number[]; // isNumber就是新名字,他可能更语义化一些
const arr: hasLen = [1];
又或者,常用语给一个联合类型定义自己的类型别名
type Name = string; // 字符串
type NameResolver = () => string; // 函数
type NameOrResolver = Name | NameResolver; // 联合类型
function getName(n: NameOrResolver): Name {
if (typeof n === “string”) {
return n;
} else {
return n();
}
}
接口声明(interface declaration)是命名对象类型的另一种方式:
9.1 使用接口
来看下面一段代码:
function getName(obj: { name: string; age: number }): void {
console.log(obj.name);
console.log(obj.age);
}
const res = getName({ name: “余光”, age: 100 });
不难理解,我们将参数 obj 内部的属性进行了类型注释,并在之后检查对应的类型,再来看看使用了接口后的代码:
interface Person {
name: string;
age: number;
}
function getName(person: Person): void {
console.log(person.name);
console.log(person.age);
}
const person1 = { name: “余光1”, age: 100 };
const person2 = { name: “余光2”, age: 200 };
getName(person1); // 余光1 100
getName(person2); // 余光2 200
类似我们在上节使用的类型别名,这个例子也同样可以运行,就跟我们使用了一个匿名对象类型一样。TypeScript 只关心传递给 printCoord 的值的结构(structure)——关心值是否有期望的属性。
**注意:**类型别名和接口非常相似,大部分时候,你可以任意选择使用。接口的几乎所有特性都可以在 type 中使用,两者最关键的差别在于类型别名本身无法添加新的属性,而接口是可以扩展的。
断言是编程术语,表示为一些布尔表达。—— 百度百科
类型断言(Type Assertion)可以用来手动指定一个值的类型。就是告诉编译器, 你不要帮我们检查了, 相信我,它就是这个类型。
断言就好比解释型强制类型转换,他会告诉你更加具体或者更不具体的类型!
值 as 类型;
有时候,我们确实需要在还不确定类型的时候就访问其中一个类型特有的属性或方法,就像这样:
interface fruits {
name: string;
getColor(): void;
}
interface person {
name: string;
getAge(): void;
}
type fruitsOrPerson = fruits | person;
function getColor(intance: fruitsOrPerson) {
return intance.getColor();
}
// 类型“fruitsOrPerson”上不存在属性“getColor”。
// 类型“person”上不存在属性“getColor”
上面的例子中,执行intance.getColor
的时候会报错。这是因为在它类型不确定时,我们使用了非共有属性或方法。
此时可以使用类型断言,将实例
断言成fruits
:
interface fruits {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
结尾
学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。
学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!**
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-RTPzN80R-1712557467834)]
[外链图片转存中…(img-xyVObHO9-1712557467835)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
[外链图片转存中…(img-z2ppOJai-1712557467835)]
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)
结尾
学习html5、css、javascript这些基础知识,学习的渠道很多,就不多说了,例如,一些其他的优秀博客。但是本人觉得看书也很必要,可以节省很多时间,常见的javascript的书,例如:javascript的高级程序设计,是每位前端工程师必不可少的一本书,边看边用,了解js的一些基本知识,基本上很全面了,如果有时间可以读一些,js性能相关的书籍,以及设计者模式,在实践中都会用的到。