3.1 基本类型和扩展类型
Typescript与Javascript共享相同的基本类型,但有一些额外的类型。
元组 Tuple
枚举 enum
Any 与Void
- 基本类型合集
// 数字,二、八、十六进制都支持
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
// 字符串,单双引都行
let name: string = “bob”;
let sentence: string = `Hello, my name is ${ name }.
// 数组,第二种方式是使用数组泛型,Array<元素类型>:
let list: number[] = [1, 2, 3];
let list: Array = [1, 2, 3];
let u: undefined = undefined;
let n: null = null;
复制代码2. 特殊类型
- 元组 Tuple
想象 元组 作为有组织的数组,你需要以正确的顺序预定义数据类型。
const messyArray = [’ something’, 2, true, undefined, null];
const tuple: [number, string, string] = [24, “Indrek” , “Lasn”]
复制代码如果不遵循 为元组 预设排序的索引规则,那么Typescript会警告。
(tuple第一项应为number类型)
2. 枚举 enum
enum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。
// 默认情况从0开始为元素编号,也可手动为1开始
enum Color {Red = 1, Green = 2, Blue = 4}
let c: Color = Color.Green;
let colorName: string = Color[2];
console.log(colorName); // 输出’Green’因为上面代码里它的值是2
复制代码另一个很好的例子是使用枚举来存储应用程序状态。
- Void
在Typescript中,你必须在函数中定义返回类型。像这样:
若没有返回值,则会报错:
我们可以将其返回值定义为void:
此时将无法 return
4. Any
Emmm…就是什么类型都行,当你无法确认在处理什么类型时可以用这个。
但要慎重使用,用多了就失去使用Ts的意义。
let person: any = “前端劝退师”
person = 25
person = true
复制代码主要应用场景有:
接入第三方库
Ts菜逼前期都用
- Never
用很粗浅的话来描述就是:“Never是你永远得不到的爸爸。”
具体的行为是:
throw new Error(message)
return error(“Something failed”)
while (true) {} // 存在无法达到的终点
- 类型断言
简略的定义是:可以用来手动指定一个值的类型。
有两种写法,尖括号和as:
let someValue: any = “this is a string”;
let strLength: number = (someValue).length;
let strLength: number = (someValue as string).length;
复制代码使用例子有:
当 TypeScript 不确定一个联合类型的变量到底是哪个类型的时候,我们只能访问此联合类型的所有类型里共有的属性或方法:
function getLength(something: string | number): number {
return something.length;
}
// index.ts(2,22): error TS2339: Property ‘length’ does not exist on type ‘string | number’.
// Property ‘length’ does not exist on type ‘number’.
复制代码如果你访问长度将会报错,而有时候,我们确实需要在还不确定类型的时候就访问其中一个类型的属性或方法,此时需要断言才不会报错:
function getLength(something: string | number): number {
if ((something).length) {
return (something).length;
} else {
return something.toString().length;
}
}
复制代码3.2 泛型:Generics
软件工程的一个主要部分就是构建组件,构建的组件不仅需要具有明确的定义和统一的接口,同时也需要组件可复用。支持现有的数据类型和将来添加的数据类型的组件为大型软件系统的开发过程提供很好的灵活性。
在C#和Java中,可以使用"泛型"来创建可复用的组件,并且组件可支持多种数据类型。这样便可以让用户根据自己的数据类型来使用组件。
- 泛型方法
在TypeScript里,声明泛型方法有以下两种方式:
function gen_func1(arg: T): T {
return arg;
}
// 或者
let gen_func2: (arg: T) => T = function (arg) {
return arg;
}
复制代码调用方式也有两种:
gen_func1(‘Hello world’);
gen_func2(‘Hello world’);
// 第二种调用方式可省略类型参数,因为编译器会根据传入参数来自动识别对应的类型。
复制代码2. 泛型与Any
Ts 的特殊类型 Any 在具体使用时,可以代替任意类型,咋一看两者好像没啥区别,其实不然:
// 方法一:带有any参数的方法
function any_func(arg: any): any {
console.log(arg.length);
return arg;
}
// 方法二:Array泛型方法
function array_func(arg: Array): Array {
console.log(arg.length);
return arg;
}
复制代码
方法一,打印了arg参数的length属性。因为any可以代替任意类型,所以该方法在传入参数不是数组或者带有length属性对象时,会抛出异常。
方法二,定义了参数类型是Array的泛型类型,肯定会有length属性,所以不会抛出异常。
- 泛型类型
泛型接口:
interface Generics_interface {
(arg: T): T;
}
function func_demo(arg: T): T {
return arg;
}
let func1: Generics_interface = func_demo;
func1(123); // 正确类型的实际参数
func1(‘123’); // 错误类型的实际参数
复制代码3.3 自定义类型:Interface vs Type alias
Interface,国内翻译成接口。
Type alias,类型别名。
以下内容来自:
Typescript 中的 interface 和 type 到底有什么区别
- 相同点
都可以用来描述一个对象或函数:
interface User {
name: string
age: number
}
type User = {
name: string
age: number
};
interface SetUser {
(name: string, age: number): void;
}
type SetUser = (name: string, age: number): void;
复制代码都允许拓展(extends):
interface 和 type 都可以拓展,并且两者并不是相互独立的,也就是说interface可以 extends type, type 也可以 extends interface 。 虽然效果差不多,但是两者语法不同。
interface extends interface
interface Name {
name: string;
}
interface User extends Name {
age: number;
}
复制代码type extends type
type Name = {
name: string;
}
type User = Name & { age: number };
复制代码interface extends type
type Name = {
name: string;
}
interface User extends Name {
age: number;
}
复制代码type extends interface
interface Name {
name: string;
}
type User = Name & {
age: number;
}
复制代码2. 不同点
type 可以而 interface 不行
type 可以声明基本类型别名,联合类型,元组等类型
// 基本类型别名
type Name = string
// 联合类型
interface Dog {
wong();
}
interface Cat {
miao();
}
type Pet = Dog | Cat
// 具体定义数组每个位置的类型
type PetList = [Dog, Pet]
复制代码
type 语句中还可以使用 typeof获取实例的 类型进行赋值
// 当你想获取一个变量的类型时,使用 typeof
let div = document.createElement(‘div’);
type B = typeof div
复制代码
其他骚操作
type StringOrNumber = string | number;
type Text = string | { text: string };
type NameLookup = Dictionary<string, Person>;
type Callback = (data: T) => void;
type Pair = [T, T];
type Coordinates = Pair;
type Tree = T | { left: Tree, right: Tree };
复制代码interface可以而 type不行
interface 能够声明合并
interface User {
name: string
age: number
}
interface User {
sex: string
}
/*
User 接口为 {
name: string
age: number
sex: string
}
*/
复制代码interface 有可选属性和只读属性
可选属性
接口里的属性不全都是必需的。 有些是只在某些条件下存在,或者根本不存在。 例如给函数传入的参数对象中只有部分属性赋值了。带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号。如下所示
interface Person {
name: string;
age?: number;
gender?: number;
}
复制代码
只读属性
顾名思义就是这个属性是不可写的,对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用 readonly来指定只读属性,如下所示:
interface User {
readonly loginName: string;
password: string;
}
复制代码上面的例子说明,当完成User对象的初始化后loginName就不可以修改了。
3.4 实现与继承:implementsvsextends
extends很明显就是ES6里面的类继承,那么implement又是做什么的呢?它和extends有什么不同?
implement,实现。与C#或Java里接口的基本作用一样,TypeScript也能够用它来明确的强制一个类去符合某种契约
implement基本用法:
interface IDeveloper {
name: string;
age?: number;
}
// OK
class dev implements IDeveloper {
name = ‘Alex’;
age = 20;
}
// OK
class dev2 implements IDeveloper {
name = ‘Alex’;
}
// Error
class dev3 implements IDeveloper {
name = ‘Alex’;
age = ‘9’;
}
复制代码而extends是继承父类,两者其实可以混着用:
class A extends B implements C,D,E
复制代码搭配 interface和type的用法有:
3.5 声明文件与命名空间:declare 和 namespace
前面我们讲到Vue项目中的shims-tsx.d.ts和shims-vue.d.ts,其初始内容是这样的:
// shims-tsx.d.ts
import Vue, { VNode } from ‘vue’;
declare global {
namespace JSX {
// tslint:disable no-empty-interface
interface Element extends VNode {}
// tslint:disable no-empty-interface
interface ElementClass extends Vue {}
interface IntrinsicElements {
[elem: string]: any;
}
}
}
// shims-vue.d.ts
declare module ‘*.vue’ {
import Vue from ‘vue’;
export default Vue;
}
复制代码declare:当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能。
这里列举出几个常用的:
declare var 声明全局变量
declare function 声明全局方法
declare class 声明全局类
declare enum 声明全局枚举类型
declare global 扩展全局变量
declare module 扩展模块
复制代码namespace:“内部模块”现在称做“命名空间”
module X { 相当于现在推荐的写法 namespace X {)
跟其他 JS 库协同
类似模块,同样也可以通过为其他 JS 库使用了命名空间的库创建 .d.ts 文件的声明文件,如为 D3 JS 库,可以创建这样的声明文件:
declare namespace D3{
export interface Selectors { … }
}
declare var d3: D3.Base;
复制代码所以上述两个文件:
shims-tsx.d.ts, 在全局变量 global中批量命名了数个内部模块。
shims-vue.d.ts,意思是告诉 TypeScript *.vue 后缀的文件可以交给 vue 模块来处理。
3.6 访问修饰符:private、public、protected
其实很好理解:
默认为public
当成员被标记为private时,它就不能在声明它的类的外部访问,比如:
class Animal {
private name: string;
constructor(theName: string) {
this.name = theName;
}
}
let a = new Animal(‘Cat’).name; //错误,‘name’是私有的
复制代码
protected和private类似,但是,protected成员在派生类中可以访问
class Animal {
protected name: string;
constructor(theName: string) {
this.name = theName;
}
}
class Rhino extends Animal {
constructor() {
super(‘Rhino’);
}
getName() {
console.log(this.name) //此处的name就是Animal类中的name
}
}
复制代码3.7 可选参数 ( ?: )和非空断言操作符(!.)
可选参数
function buildName(firstName: string, lastName?: string) {
return firstName + ’ ’ + lastName
}
// 错误演示
buildName(“firstName”, “lastName”, “lastName”)
// 正确演示
buildName(“firstName”)
// 正确演示
buildName(“firstName”, “lastName”)
复制代码非空断言操作符:
能确定变量值一定不为空时使用。
与可选参数 不同的是,非空断言操作符不会防止出现 null 或 undefined。
let s = e!.name; // 断言e是非空并访问name属性
复制代码4. Vue组件的Ts写法
从 vue2.5 之后,vue 对 ts 有更好的支持。根据官方文档,vue 结合 typescript ,有两种书写方式:
**Vue.extend **
import Vue from ‘vue’
const Component = Vue.extend({
// type inference enabled
})
复制代码vue-class-component
import { Component, Vue, Prop } from ‘vue-property-decorator’
@Component
export default class Test extends Vue {
@Prop({ type: Object })
private test: { value: string }
}
复制代码理想情况下,Vue.extend 的书写方式,是学习成本最低的。在现有写法的基础上,几乎 0 成本的迁移。
但是Vue.extend模式,需要与mixins 结合使用。在 mixin 中定义的方法,不会被 typescript 识别到
,这就意味着会出现丢失代码提示、类型检查、编译报错等问题。
菜鸟才做选择,大佬都挑最好的。直接讲第二种吧:
4.1 vue-class-component
我们回到src/components/HelloWorld.vue
{{ msg }}
=========
复制代码有写过python的同学应该会发现似曾相识:
vue-property-decorator这个官方支持的库里,提供了函数 **装饰器(修饰符)**语法
- 函数修饰符 @
“@”,与其说是修饰函数倒不如说是引用、调用它修饰的函数。
或者用句大白话描述:@: “下面的被我包围了。”
举个栗子,下面的一段代码,里面两个函数,没有被调用,也会有输出结果:
test(f){
console.log(“before …”);
f()
console.log(“after …”);
}
@test
func(){
console.log(“func was called”);
}
复制代码直接运行,输出结果:
before …
func was called
after …
复制代码上面代码可以看出来:
只定义了两个函数:test和func,没有调用它们。
如果没有“@test”,运行应该是没有任何输出的。
但是,解释器读到函数修饰符“@”的时候,后面步骤会是这样:
去调用test函数,test函数的入口参数就是那个叫“func”的函数;
test函数被执行,入口参数的(也就是func函数)会被调用(执行);
换言之,修饰符带的那个函数的入口参数,就是下面的那个整个的函数。有点儿类似JavaScript里面的
function a (function () { … });
- vue-property-decorator和vuex-class提供的装饰器
vue-property-decorator的装饰器:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
HTTP
-
HTTP 报文结构是怎样的?
-
HTTP有哪些请求方法?
-
GET 和 POST 有什么区别?
-
如何理解 URI?
-
如何理解 HTTP 状态码?
-
简要概括一下 HTTP 的特点?HTTP 有哪些缺点?
-
对 Accept 系列字段了解多少?
-
对于定长和不定长的数据,HTTP 是怎么传输的?
-
HTTP 如何处理大文件的传输?
-
HTTP 中如何处理表单数据的提交?
-
HTTP1.1 如何解决 HTTP 的队头阻塞问题?
-
对 Cookie 了解多少?
-
如何理解 HTTP 代理?
-
如何理解 HTTP 缓存及缓存代理?
-
为什么产生代理缓存?
-
源服务器的缓存控制
-
客户端的缓存控制
-
什么是跨域?浏览器如何拦截响应?如何解决?
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
更新**
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-H5qoGzsq-1712195858883)]
HTTP
-
HTTP 报文结构是怎样的?
-
HTTP有哪些请求方法?
-
GET 和 POST 有什么区别?
-
如何理解 URI?
-
如何理解 HTTP 状态码?
-
简要概括一下 HTTP 的特点?HTTP 有哪些缺点?
-
对 Accept 系列字段了解多少?
-
对于定长和不定长的数据,HTTP 是怎么传输的?
-
HTTP 如何处理大文件的传输?
-
HTTP 中如何处理表单数据的提交?
-
HTTP1.1 如何解决 HTTP 的队头阻塞问题?
-
对 Cookie 了解多少?
-
如何理解 HTTP 代理?
-
如何理解 HTTP 缓存及缓存代理?
-
为什么产生代理缓存?
-
源服务器的缓存控制
-
客户端的缓存控制
-
什么是跨域?浏览器如何拦截响应?如何解决?
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算