运行ts:
1.安装typescript 然后使用tsc命令把ts文件编译成js,然后运行js
2.安装ts-node,@type/node,用ts-node能直接运行ts文件
声明变量:
// 格式: 声明关键字 变量名:变量类型 = 变量值
let val:string = 'Suk'
// 变量类型:number,string,boolean,undefined,null,object,array,any,never,void any是任意类型,不确定的时候用,void是函数无返回值类型时用,never是不存在的值的类型,通常用作死循环和抛出异常的类型
// never类型是所有类型的子类型,所有类型都是never类型的父类
let val2 = 123 // 如果变量声明和赋值在同一行进行,那么就会发生类型推断,不用声明具体类型,自动根据值识别类型,但是下一次赋值时就不能赋值别的类型的值了
let val3:number | string | boolean = 0 // 联合类型,可以允许接收多种允许的类型
// 比如使用prompt函数时,用户确定返回输入的字符串,否则取消返回null,这里就会有两个可能的类型
let val4:string | null = window.prompt('请输入:')
声明数组:
// 声明数组的两种方式:
let arr1: string[] = ['赵云', '橘右京', '上官婉儿'] // 推荐方式xxx[]
let arr2: Array<string> = ['赵云', '橘右京', '上官婉儿']
console.log('arr1:', arr1)
console.log('arr2:', arr2)
声明元组(元组可以确切的知道数组里有几个元素和元素类型):
// 声明元组可以限制数组的元素类型和数组的长度个数
let arr: [string, number, boolean] = ['Suk', 18, true]
console.log('arr:', arr)
声明枚举:
enum Gender {
Male = 1,
Female = 2,
Unknow = 3
}
// 如果枚举值不给初始值的话默认从0开始
enum Gender2 {
Male, // 0
Female, // 1
Unknow // 2
}
console.log(Gender.Male) // 1
console.log(Gender.Female) // 2
console.log(Gender.Unknow) // 3
// 创建枚举变量
let userSex: Gender2 = Gender2.Female
// 判断是否为女生
if (Gender2.Female === userSex) {
console.log('是女生')
} else {
console.log('不是女生')
}
声明函数:
// 普通函数
function fn1 (a: number, b: number): number {
return a + b
}
console.log(fn1(1, 2))
// 箭头函数 ?表示可不传 或者设置默认值替代?
const fn2 = (a: number, b?: number): number => {
return b ? a - b : a
}
console.log(fn2(1, 2))
console.log(fn2(1))
// 如果是前面的不传使用默认值后面的必传,那么不传的我们传递undefined就会使用默认值
const fn3 = (a: number = 1, b: number): number => {
return a - b
}
console.log(fn3(undefined, 2))
// 剩余参数:可以传不限数量个参数 必须在最后一个形参位置,而且是一个数组,使用展开运算符...表示
const fn4 = (a: number, b: number, ...nums: Array<number>): number => {
let sum: number = a + b
for (const num of nums) {
sum += num
}
return sum
}
console.log(fn4(1, 2, 7, 8, 9))
// 方法重载
function setField (name: string): string
function setField (name: string, age: number): string
function setField (name: any, age?: any): any {
if (!age) {
return `我叫${name}`
} else {
return `我叫${name},今年${age}岁了`
}
}
console.log(setField('Suk'))
console.log(setField('Suk', 1))
声明类:
/*
属性修饰符: private protected public
private:私有,只有本类中才能使用
protected:保护的,只有本类和子类中才能使用
public:公开的,都能访问不受限制
*/
class Father {
private gender: number = 0
protected name: string
public constructor (name: string) {
this.name = name
}
public sayHi (): string {
return `你好我叫${this.name}`
}
public eat (): string {
return `我喜欢吃汉堡`
}
}
// 继承
class Son extends Father {
// 静态属性
static language: string = '中文'
// 静态方法
public static speak (): string {
return `我说${Son.language}` // 调用静态方法或属性都是用类名调用
}
public constructor (name: string) {
// 第一行必须调用父类构造
super(name)
}
public eat (): string {
return `我喜欢吃披萨`
}
}
const son = new Son('Suk')
console.log(Son.speak())
console.log(son.sayHi())
console.log(son.eat()) // 父子类都有优先调用子类的
// 多态:同一种事物的不同表现形态 通过继承抽象类或者实现接口实现
// 抽象类
abstract class Person {
protected name: string
public constructor (name: string) {
this.name = name
}
// 定义跑的抽象方法
abstract run (): any
}
// 继承抽象类 必须实现抽象类的抽象方法run
class Student extends Person {
public constructor (name: string) {
super(name)
}
public run (): string {
return `${this.name}在奔跑`
}
}
const student1 = new Student('Suk')
const student2 = new Student('Susuk')
console.log('学生1:', student1.run())
console.log('学生2:', student2.run())
声明接口:
// 定义接口来限制参数类型,起到一个规范约束作用 ?表示可选属性
// 方法形参中可选属性必须在必填属性后面,也就是必填属性必须放前面传入,否则会报错
interface User {
username: string
age: number
gender: number
school?: string
}
const fn = (user: User): string => {
return `${user.username}今年${user.age}岁,性别为${
user.gender === 0 ? '男' : '女'
}`
}
// 如果想在传入对象中写接口中不存在的属性会报错
// console.log(fn({tel:123, username: 'Suk', age: 18, gender: 0 }))
// 将对象定义在外面再传入进来就不会报错
const obj = { tel: 123, username: 'Suk', age: 18, gender: 0 }
console.log(fn(obj))
// 函数接口 限制函数
interface Fn {
(user: string): string
}
const fn4: Fn = (user: string): string => {
return user
}
console.log(fn4('Susuk'))
// 可索引接口限制数组
interface Arr {
// 索引是数字类型,值是字符串类型
[index: number]: string
}
function fn2 (arr: Arr): void {
console.log(arr)
}
fn2(['1', '2', '3'])
type关键字给常用类型起别名:
type Student = (number | string)[]
// 这样就不用每次都写全了 麻烦 写别名就行
const student: Student = ['Suk', 123]
console.log(student)
类型推导:
当直接声明一个变量并且明确赋值时就会自动推断变量和类型,不用手动加上类型
类型断言:
方式一:使用<类型>变量
方式二:使用变量 as 类型
// 断言为string
const num = <string>1;
const num = 1 as string;
字面量类型:
当变量的值很明确是哪些时,直接用字面量类型+联合类型:
const a = '1' // 这里的1就是一个字面量类型,可以当类型直接用
const b:a = '1' // 字面量类型限制死了值,是什么值就是什么值
// 因为常量不可变 所以定义任意一个值都能作为一个字面量类型使用
// 使用场景: 比如游戏中移动的方向只有上下左右,那么就可以用字面量类型+联合类型指定是最好的:
const move = (direction: 'up' | 'down' | 'left' | 'right') => {}
推荐使用字面量类型+联合类型替代枚举更直观,简洁,高效
具有隐士any类型的情况:
1.声明变量不提供类型也不赋默认值的情况
2.函数形参不加类型的情况
非空断言(!):告诉ts这里不是null/undefined
// 有时可能自己确定访问的肯定不是null或undefined,就用非空断言 告诉ts不是空
const dom = document.getElementById('id')!;
console.log(dom.id)
console.log(dom!.classList)