安装及自动编译配置
安装
npm i typescript -g
验证安装成功
tsc -v
# 自动编译
1. 生成配置文件`tsc -init`
2. 解除配置项中'outDir'注释
3. 在vscode点击终端->运行任务->typescript->监视tsconfig.json
数据类型
# 布尔类型(boolean)
var demo:boolean = true
# 数字类型(number)
var demo:number = 123
# 字符串类型(string)
var demo:string = '123'
# 数组类型(array)
var demo:number[] = [1,2,3]
var demo:Array<number>= [1,2,3]
# 元组类型(tuple)属于数组的一种
var demo: [number, string, number] = [1, '123', 3] //与类型一一对应
# 枚举类型(enum)
enum demo {
success = 1,
error = 0
}
# 任意类型(any)
var demo: any = 324324
# null和undefined
var demo: null =null
# void类型
没有任何类型,一般用于定义方法的时候没有返回值
function fn(): void {
console.log('无返回值');
return
}
# never类型
never是其他类型,包括null和undefined的子类型,代表从来不会出现的值,一般不用,可以用any类型去代替
函数
1. `?`可以设置可选项
2. 可选项可以设置默认值
3. 可选项要放在形参的末尾
function fn(name: string, age?: number, sex: string = '男'): string {
return `姓名${name}年龄${age}性别${sex}`
}
alert(fn('hfd', 18))
在es5中重载下面的函数会覆盖上面的函数,ts中的重载是通过同一个函数接受不同的参数来执行不同的操作。
// es5写法
function demo(name) { }
function demo(name, age) { } // 会覆盖上面的
//ts中函数的重载
function demo(name: string): string
function demo(name: string, age: number): string
function demo(name: string, age?: number): string {
if (age) {
return `我的名字:${name},我的年龄${age}`
} else {
return `我的名字:${name}`
}
}
alert(demo('hfd', 18))
类
// 类
class person {
public name: string
constructor(name: string) {
this.name = name
}
run() {
alert(this.name)
}
}
var p = new person('张三')
p.run()
//继承(如果子类有和父类相同名称的方法,执行子类的方法)
class web extends person {
constructor(name: string) {
super(name)
}
run() {
alert(this.name + '子类')
}
}
var w = new web('李四')
w.run()
# 修饰符
1. public公有,在当前类、子类、类外都可以访问,不加修饰符默认为public
2. protected保护类型,在当前类里、子类可以访问,类外不可以访问
3. private私有,在类里面可以访问,子类、类外部都不可以访问
静态属性和静态方法
# 静态属性和静态方法
class person {
name: string
static age: number = 20
constructor(name: string) {
this.name = name
}
run() {
return alert(`${this.name}`)
}
static work() {
// return alert(`${this.name}在工作`) 在ts中静态方法不可以直接访问类里面的属性,需要定义静态属性
return alert(person.age)
}
}
person.work()
多态
# 多态(父类定义一个方法不去实现,让继承他的子类去实现,每个子类有不同的表现方式)
class animal {
name: string
constructor(name: string) {
this.name = name
}
eat() {
console.log('吃的方法');
}
}
class dog extends animal {
constructor(name: string) {
super(name)
}
eat() {
console.log(this.name + '吃猫粮');
}
}
class cat extends animal {
constructor(name: string) {
super(name)
}
eat() {
console.log(this.name + '吃猫粮');
}
}
const c = new cat('猫咪')
c.eat()
抽象类
1. ts中的抽象类,提供其他类型继承的基类,不能直接被实例化。
2. 用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在被继承的类中实现。
3. abstract抽象方法只能放在抽象类中
4. 抽象类和抽象方法用来定义标准,如下代码(继承animal的类都需要实现eat方法)
abstract class animal {
name: string
constructor(name: string) {
this.name = name
}
abstract eat():any
}
// const a = new animal() // 不可以创建抽象类的实例
class cat extends animal {
constructor(name: string) {
super(name)
}
// 抽象类的子类必须实现抽象类里的抽象方法
eat() {
console.log(this.name + '吃猫粮');
}
}
const c = new cat('哇卡巴卡')
c.eat()
接口
接口就是行为和动作的规范,对批量的方法进行约束
// 定义接口
interface rule {
one: string;
two: number
}
// 使用
class demo {
name: rule
constructor(name: rule) { this.name = name }
run() {
console.log(this);
console.log(this.name.one, this.name.two);
}
}
var d = new demo({ one: '测试', two: 1 })
d.run()
加密函数类型接口
//加密函数类型接口
interface fun {
(number: string, value: string): string
}
var demo: fun = function (number: string, value: string): string {
return ''
}
可索引接口
// 可索引接口,对对象或者数组进行约束,下标为string的是对象,下标是number的是数组
interface obj {
[index: string]: string
}
var demo: obj = { name: '1' }
interface arr {
[index: number]: number
}
const demo: arr = [1, 2, 3]
类类型接口
// 类类型接口
interface fun {
eat(food: string): void
name: string
}
class demo implements fun {
name: string
constructor(name: string) {
this.name = name
}
eat(food: string): void {
console.log(this.name + '爱吃' + food);
}
}
var d = new demo('小猫咪')
d.eat('小鱼干')
接口继承
// 接口继承
interface animal {
name: string
eat(str: string): void
}
// 接口继承接口
interface person extends animal {
work(str: string): void
}
class demo implements person {
name: string
constructor(name: string) {
this.name = name
}
// 使用了接口就需要有接口规定的方法
eat() { }
work() { }
}
class ext {
name: string
constructor(name: string) {
this.name = name
}
game(game: string) {
console.log(this.name + '在玩' + game);
}
}
// 既可以继承类也可以实现接口
class demo2 extends ext implements person {
constructor(name: string) {
super(name)
this.name = name
}
eat() { }
work() { }
}
const d = new demo2('hfd')
d.game('开心消消乐')
泛型
泛型可以帮助我们避免重复的代码,解决了类、方法、接口的复用性,以及对不确定数据类型的支持(类型校验)
// 泛型函数
function fn<T>(value: T): T { // T泛型
return value
}
fn<string>('泛型')
// 泛型类
class demo<T>{
log(value: T): T {
return value
}
}
const d = new demo<number>()
console.log(d.log(123));
泛型接口
// 泛型接口(方法1)
interface animal {
<T>(value: T): T
}
var d: animal = function fn<T>(value: T): T {
return value
}
console.log(d<string>('123'));
// 泛型接口(方法2)
interface animal<T> {
(value: T): T
}
var d: animal<string> = function fn(value) {
return value
}
console.log(d('1234'));
把类作为参数类型的泛型类
// 写法1
class ext {
name: string | undefined
sex: string | undefined
}
class demo {
constructor(str: ext) {
console.log(str);
}
}
const d = new demo({ name: 'hfd', sex: '男' })
// 写法2
class ext {
name: string | undefined
sex: string | undefined
}
class user<T>{
add(data: T):boolean {
console.log('这是data数据', data);
return true
}
}
const d = new ext()
d.name = '测试的名字'
d.sex = '女'
const data = new user<ext>()
data.add(d)
模拟数据库操作
// 模拟操作数据库
interface DBL<T> {
add(info: T): boolean;
edit(info: T, id: number): boolean;
delete(id: number): boolean;
get(id: number): boolean
}
class user {
name: string | undefined
age: number | undefined
}
// 定义一个操作mysql数据库的类 注意:实现泛型接口这个类也应该是一个泛型类
class mysql<T> implements DBL<T> {
constructor() {
// 在这里可以进行数据库连接等操作
}
add(info: T): boolean {
console.log(info);
return true
}
edit(info: T, id: number): boolean {
if (info && id) {
// 提交到数据库
console.log('修改成功');
}
return true
}
delete(id: number): boolean {
if (id) {
console.log('删除成功');
}
return true
}
get(id: number): boolean {
if (id) {
console.log('查询成功');
}
return true
}
}
const u = new user()
u.name = 'hfd'
u.age = 18
const m = new mysql<user>() // 类作为参数来约束数据传入的类型
m.add(u)
m.edit(u, 123)
m.delete(123)
m.get(123)
命名空间
在代码量较大的情况下,为了避免变量命名冲突,可以将相似功能的函数、类、接口等放到命名空间内
# 命名空间和模块化的区别
命名空间: 内部模块,主要用于组织代码,避免命名冲突
模块: ts外部模块,侧重代码的复用
// 命名空间
interface animal {
name: string
games(game: string): void
}
namespace A {
// 在命名空间内demo为私有类,所以需要导出才可以用
export class demo implements animal {
name: string
constructor(name: string) {
this.name = name
}
games(game: string): void {
console.log(this.name + "在玩" + game);
}
}
}
namespace B {
// 在命名空间内demo为私有类,所以需要导出才可以用
export class demo implements animal {
name: string
constructor(name: string) {
this.name = name
}
games(game: string): void {
console.log(this.name + "在玩" + game);
}
}
}
// 访问方法
const cat = new A.demo('小猫咪')
cat.games('开心消消乐')
const dog = new B.demo('小狗狗')
cat.games('王者荣耀')
类型推论
变量`Name`的类型被推断为string,这种推断发生在初始化变量,设置默认参数值时,如果在声明时没有赋值则会被默认推断为any任意类型的值!
高级类型
交叉类型(Intersection Types)
interface IPerson {
id: string;
age: number;
}
interface IWorker {
companyId: string;
}
type IStaff = IPerson & IWorker //主要通过这段代码实现
const staff: IStaff = {
id: 'E1106',
age: 5,
companyId: '蛋仔乐园'
};
console.dir(staff)
交叉类型就是将多个类型合并成为一个类型,让这个类型同时拥有所有类型的特性!
联合类型(Union Types)
interface person {
name: string
age:number | string
}
联合类型表示一个值可以是几种类型之一, 我们用竖线( `|`)分隔每个类型!如上就age就表示可以是number类型也可以是string类型的数据(只能赋值指定的类型)!
Pick 和 Omit
interface Person {
name: string;
age: number;
id: number;
}
type Woman = Pick<Person, "name" | "id">;
type EditUser = Omit<Person, "id">;
# Pick
主要是从一个已知的类型中,取出子集,作为一个新的类型返回,上面的代码就表示从Person中取出name和id作为新的类型!
# Omit
Omit与Pick作用相似,只不过Omit是以一个类型为基础支持剔除某些属性,然后返回一个新类型,上面的代码就表示从Person去掉id只留下其他属性,组成一个新的类型!
小结
学到这里TS大概能够完成现在的工作了!更多的可以参考TS官方文档来学习,加油!