- TypeScript 的核心原则之一是对值所具有的结构进行类型检查。鸭式辨型法 结构性子类型化
这里需要注意的是,类型断言只是用来判断变量的数据类型,是不能用来转换变量的数据类型。
自己编写类型断言试一试
- '尖括号’语法:<类型>值
(<string>someValue)
- 'as’语法:值 as 类型
(someValue as string)
当然也可以断言为 number boolean null undefined … (看需求)
// 类型断言
let someValue: any = 1234567
// '尖括号'语法:<类型>值
let somelength: number = (<string>someValue).length
// 'as'语法:值 as 类型
let somelength1: number = (someValue as string).length
console.log(somelength);
console.log(somelength1);
function getlength(a: number | string) {
if ((<string>a).length) {
return (<string>a).length
} else {
return a.toString.length
}
}
const num = getlength('123456') // 6
console.log(num);
console.log(getlength('1234567890')); //10
在 ts 文件中报错或者有任何的不明白地方都可以把鼠标放到变量上,自动会显示类型推断的信息或者各种信息
初学者可以多多尝试
ts 里面可以对 类(class) 使用几个修饰符
public
公有
private
私有属性 只能在类中访问
readonly
只读属性 可以访问不可修改
protected
子类可以访问
TypeScript
- 所有数据都是有来源的。
- vue3 默认用 typeScript 去写。
- 面试 null undefault 的区别
- 还有就是那六种 包不包括 Array
javascript 数据类型有 7 种
Object
- 原始的数据类型 null undefined Number Boolean String Symbol (BigInt)
- 声明变量的时候定义的数据类型是小写。
- undefied 是所有数据类型的子级,设置变量不想赋初始值可以设置为 undefined
- null 和 undefined 基本不会设置。
- void 空值,一般定义在函数的返回值里面,如果定义的变量刚开始的时候没有赋值,那么后期可以赋任何的值,但是一旦赋值上就不能再修改。可以说是类型推论的一种。
- 类型推论:刚开始定义数据类型的时候没有声明变量数据类型,赋值的时候,类型推论就会帮你自动定义数据类型。意思和 js 的用法一样。
- 联合类型:(number | string),赋值的时候只能是这里中的其中一种。联合类型和类型推论可以应用到多方面,比如说数组也可以用联合数据类型。应用的很广。
- 元组:已知数量和类型的数组,赋值不对应就会失败。一般很少用。
- 对象类型:也是接口类型,有只读属性 readonly,可选属性?,增加属性[]。
- 函数的类型5种:
- 标准函数类型函
- 空值函数类型
- 参数类型 => 返回值类型
- 类型推论:可以省略变量,省略函数类型声明
- 箭头函数。
- 创建了一个函数
hello 17 (6) [1, 2, 3, 4, 5, 65]
- 创建一个函数:将传递的数字或者字符串倒序输出。
安装 TypeScript
ts 需要编译之后才能正常运行在浏览器或者 node 环境下。
全局安装一个 typescript 工具 npm install -g typescript
,将 ts 编译成 js 文件,执行命令 tsc index.ts
直接在文件内编译成 index.js
全局安装一个 ts-node 工具 npm install -g ts-node
,执行命令 ts-node index.js
可以直接在 node 环境下运行 ts 文件
每次写完 inedx.ts 文件之后要执行 tsc index.ts
才能生效。
基础类型
boolean
// 布尔
let isDemo: boolean = true;
let isDemo1: Boolean = new Boolean(false);
let res: RegExp = /[0-9]/;
console.log(isDemo);
number
// 数字
// 变量不想赋值成任何的初始值,可以赋值成 undefined
let num: Number = undefined;
string
// 字符串
let str: String = "hello";
undfined
// undfined 是所有类型的子类型
let und: undefined = undefined;
null
// null
let nulldemo: null = null;
void
// 空值 void 只能是 null 和 undefined 定义一个空值没有什么用 一般在函数的返回值的时候设置。
let unusable: void = undefined;
let unusableDemo; //定义的时候没有赋值,后期赋什么值都行
// unusableDemo = 'hello'
// unusableDemo = 1234
any
// Any
let anyThing: any = "hello";
// anyThing = 123
类型推论
类型推论: 声明变量的时候没有声明类型 如果赋值了 类型推论就会帮助你自动定义类型
let num1 = 10;
// num1 = 'hello' //只能赋值 number
联合类型
既可以是数字类型也可以是字符串类型
// 联合类型
let number1: number | String = "hello"; // number | String 只能是两个类型
Array
// 数组的类型
// 数字数组
// 数字数组 | String
// 数组的泛型
let arr: number[] = [1, 2, 3, 4]
let arr1: Array<number> = [1, 2, 3]
let arr2: Array<string> = ['1', '2', '3']
let arr3: (number | string)[] = [19, 8, 7, 'hello']
let arr4: Array<number | string> = [1, 2, 3, 'hello']
// console.log(arr, arr1, arr2, arr3, arr4);
元组
// 元组
// 元组类型允许表示一个已知元素数量和类型的数组
let x: [string, number] = ["hello", 10]; // OK
// let y: [string, number] = [10, "hello"]; // 赋值不对应会失败
对象类型 接口
// 对象类型 接口
interface Obj {
// 只读属性
readonly firstName: string
// 固定属性
name: string
// 可选属性
age?: number
// 增加属性
[Never: string]: any
}
let User1: Obj = {
firstName: '王',
name: '小三',
age: 18,
Never: ['增加属性', 123, 435]
}
console.log(User1);
// {firstName: "王", name: "小三", age: 18, Never: Array(3)}
函数类型
function fun22(a: number, b: number): void {
console.log(a + b);
}
function fun12314(a: number, b: number): number {
return a + b
}
// 函数类型
// 函数的创建
// 1. 函数创建
function fun(a, b) {
return a + b
}
// 2. 表达式创建
const add1 = (a, b) => a + b
// 在 TypeScript 内 函数声明,需要声明参数和返回值的类型。
function add2(a: number, b: number): number {
return a + b
}
add2(1, 2) //规定了两个就是只传两个。
// 函数没有返回值,返回值类型设置成 void
function fun1(x: string): void {
console.log(x);
}
// console.log(fun1('hello'))
// 必须设置变量的类型 函数类型 (参数类型) => 返回值类型
// 这是自动赋值
const add3: (a: number, b: number) => number = function (a: number, b: number): number {
return a + b
}
// 这是类型推论 可以省略变量 函数类型声明
const add4 = function (a: number, b: number): number {
return a + b
}
// 箭头函数
const add5 = (a: number, b: number): number => a + b
// 创建新的函数测试
function fun2(x: string = 'hello', y?: string, ...rest: number[]): void {
console.log(x + y);
console.log(rest);
}
fun2('hello', 'world', 34, 432, 34, 5, 3)
// 创建一个函数 将传递的数字或者字符串进行倒序输出
function reverse(x: number | string): number | string {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''))
} else {
return x.toString().split('').reverse().join('')
}
}
// console.log(reverse('123456'));
// console.log(reverse('hello'));
高级类型
// 高级类型
// 类型断言 将联合类型断言为其中的某一种类型
// 值 as 类型 这种语法用的比较多
// <类型>值
let xx: string | number = '0'
// 测试一个小例子
interface Cat {
name: string
// 这样方法就写死了
// run: (a: number, b: number) => number
// 定义一个 run 方法
run(): void
}
interface Fish {
name: string
swim(): void
}
const fish: Fish = {
name: '小鱼',
swim: () => {
console.log('自由自在的游');
}
}
function getName(animal: Cat | Fish): string {
return animal.name
}
console.log(getName(fish), fish.swim()); // 自由自在的游 小鱼 undefined
function isFish(animal: Cat | Fish): boolean {
// if (typeof (animal as Fish).swim === 'function') {
if (typeof (<Fish>animal).swim === 'function') {
// 在这直接 判断 animal 是否拥有 awin 属性
// 会报错 ts 编译失败
// 需要使用类型断言 先断言 animal 是 Fish 接口类型
return true
}
return false
}
console.log(isFish(fish)); // true
// 将任意一个类型断言成 any
// (function x() {
// // const $ = '很牛的函数'
// // 一顿操作
// (window as any).jQuery = 10
// })()
// window 全局对象 在 ts 中默认不能使用,需要定义,只有文件运行在 浏览器上才会有 window
内置对象
// 内置对象
// 创建一个 时间实例
const date = new Date()
// console.log(date); //会出现现在的时间 2020年12月9日17:13:49
const re = new RegExp("[abc]")
console.log(re); // [abc]
// DOM document
console.log(document);
// 单一元素类型 HTMLElement
const box: HTMLElement = document.querySelector('.box')
console.log(box); //<div class="box"></div>
// 元素集合类型 NodeList
const box1: NodeList = document.querySelectorAll('box')
console.log(box1); // NodeList []
// MouseEvent 鼠标事件对象 的类型
box.onclick = function (e: MouseEvent): void {
console.log(e); //点击盒子的时候才会出现
// MouseEvent {isTrusted: true, screenX: 79, screenY: 176, clientX: 79, clientY: 73, …}
}
box.addEventListener('click', function (e: MouseEvent) {
console.log(e.target) // <div class="box"></div>
})
// BOM window
// 全局对象 window ,用是能用,但是增加一个属性的时候是不行的。
console.log(window);
(window as any).$ = '10'
// 这样在 js 是不行的。
console.log((<any>window).$); // 10
类型别名
// 类型别名
// 使用 type 创建任意的类型别名
type NumOrStr = number | string;
type NumArr = number[];
const Num: NumOrStr = "10";
const arr11: NumArr = [1, 23, 4, 56, 7, 45, 23];
字面量类型
// 字面量类型
type Fruit = "apple" | "orange" | "taozi";
type Num = 1 | 2 | 3;
const str1: Fruit = "apple";
const num11: Num = 1;
枚举
// 枚举类型
// 一般存储的都是常量
enum Days { Sun, Mon, Tue, wed, Thu, Fri, Sat }
// const day = Days['Mon']
// console.log(day);
const day: string = 'Mon'
if (Days[1] === day) {
console.log('周一');
}
console.log(Days);
类
// 类
// 类(class) 和 接口(interface) 有什么区别
// 接口有一些局限性,this 拿到的是 global
interface Preson {
name: string;
age: number;
// say: () => {
// console.log(this.name);
// }
say(): void;
}
// 类的话就不需要定义类型
class Person {
// 类内的属性和方法需要先定义好类型
// 然后 constructor 内才能给这些属性或者方法赋值, constructor 内赋值的属性和方法需要提前声明
name: string;
age: number;
// 注意 上面的 name age 和下面的 name age 代表的意思是不一样的
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
say() {
console.log(this.name);
}
}
// 用 new 比较合适
const user: Person = new Person("小黑", 2);
console.log(user); //Person {name: "小黑", age: 2}
继承
// 继承
// 1. 创建类
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
sayHi() {
console.log(`my name is ${this.name}`);
}
}
// 2. 继承
class Cat extends Animal {
constructor(name: string) {
super(name);
}
}
// 3. 实例
const cat1 = new Cat("小绿");
console.log(cat1); // Cat {name: "小绿"}
泛型
// 泛型
// 就是定义的时候不知道它是什么,用完之后了才知道它是什么。
// 创建任意长度的一个数组,而且创建出来的数组每一项是有默认值的。
function createArray(length: number, value: any) {
let res = []
for (let i = 0; i < length; i++) {
res.push(value)
}
return res
}
console.log(createArray(4, 'x'));
网上的类型推论
let a: number | string;
a = 1; // 类型推论:此时变量a为number类型
a = "string"; // 类型推论:此时变量a为string类
let a: any;
a = 1; // 类型推论:变量a为number类型
a = "string"; // 类型推论:变量a为string类型
a = true; // 类型推论:变量a为boolean类型
现在我们先来模拟一种实际开发中遇到的情况:输入一个变量 a,返回数据的长度。这种开发要求下,我们在 JavaScript 中可以利用字符串独有的 length 属性来区别数据类型或者是用 typeof()来判断数据类型,经过判断后再来处理对应的数据,然后返回我们想要的结果,但是在 typescript 中,我们可以采用同样的方法吗?如下:
function getResult(a: string | number): number {
if (a.length) {
return a.length;
} else {
return a.toString().length;
}
}
// 执行编译指令:Property 'length' does not exist on type 'number'.
- 在这里,我们定义函数 getResult 的输入参数为联合类型(字符串或者数值类型),输出类型为数值类型,不清楚函数定义的同胞们可以参考上一篇文章(函数的定义及特性)。可以看到当我们执行编译指令的时候,编译报错了,报错信息就是:length 属性不存在于 number 类型中。我们之前提到过,访问联合属性的变量,需要访问两个类型或者其子类型共有属性才可以,所以在 typescript 中不能采用 length 的特点来进行判断区分。但是利用 typeof()时没有任何问题的,如下:
function getResult(a: string | number):number {
if (typeof(a) === 'string') {
return a.length;
} else {
return a.toString().length;
}
}
let b = getResult('hahahaha'); // 输出长度为8
- 但是,如果非要使用length属性呢?这里,我们介绍一种在typescript中使用的方法:类型断言,字面理解就是确定变量的数据类型。它断言的语法主要有两种:
let someValue: any = "this is a string";
// '尖括号'语法:<类型>值
let strLength: number = (<string>someValue).length;
// 'as'语法:值 as 类型
let strLength: number = (someValue as string).length;
所以,利用这种类型断言的方法,我们就可以利用length的特性来作判断,代码如下:
function getResult(a: string | number):number {
if ((<string>a).length) {
return (<string>a).length; // 切记:这里也需要加上类型断言
} else {
return a.toString().length;
}
}
let b = getResult('hahahaha'); // 长度为8
这里需要注意的是,类型断言只是用来判断变量的数据类型,是不能用来转换变量的数据类型。