ts基本语法

简介

ts 没有扩展 js 的内容,只是用来类型检测!
ts 最终是需要ts解析器(npm i -g typescript)解析成js才能运行的,而这个解析器是用node写的,所有必须先装NodeJS。
详细教程可以直接去TypeScript入门教程查看。

  • JavaScript 是一门解释型语言,没有编译阶段,是动态类型
  • TypeScript 在运行前需要编译为 JavaScript,在编译阶段就会进行类型检查,是静态类型
  • 它们都是弱类型

编译执行.ts

编译.ts

npm install -g typescript

就可以直接编译你的 .ts 文件到 .js

tsc xxx.ts

就会生成对饮的 .js 文件,然后直接使用node命令执行即可

node xxx.js

编译执行.ts

如果想一步到位实现编译+执行的话,使用 ts-node

npm install -g ts-node
ts-node xxx.ts

tsconfig.json

tsc --init

就会生成 tsconfig.json ,可以根据项目需要对其进行修改配置你想要的 ts 提示

类型

默认情况下 nullundefined 是所有类型的子类型

简单基础类型

let isDone:boolean = false // var isDone = false;
let decLiteral: number = 6 // var decLiteral = 6;
let myName: string = 'Jane' // var myName = 'Jane';
// 在不确定类型的时候尽量使用 unknown类型,不用any类型,unknown是安全的any类型
let a: unknown = 10
let anyThing: any = 'hello' // var anyThing = 'hello';
// void 类型表示没有返回值(没有return xxx)
function add(): void {
  console.log('没有返回值')
}

联合类型

let myFavoriteNumber: string | number // var myFavoriteNumber;

数组

// 两种方式
let numberArray: number[] = [1, 2, 3] // var numberArray = [1, 2, 3];
let numberArray1: Array<number> = [4, 5, 6] // var numberArray1 = [4, 5, 6];

let arr: (string | number)[] = [1, 'a']

let arr: {name: string, age: number}[] = [
  {name: 'Jane', age: 17},
  {name: 'Jian', age: 20}
]

元组

// 元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同,超出部分采用的是联合类型
// 注意:类型顺序要对应,相当于plus版的数组了
let data: [number, string, boolean] = [2, '3', true] // var data = [2, '3', true];

枚举

enum Direction {
    Up = 1, // 不赋值默认从0开始
    Down,
    Left,
    Right
}

console.log(Direction.Down) // 2
console.log(Direction[1]) // Up

Direction.Up 的值为 1Down2Left3Right4(也可以指定为指定的字符串值)。

类型推论

// 定义变量时没有给变量指定类型但是赋值了,TypeScript 会依照类型推论的规则推断出一个类型,后面就不能将其赋值其他类型了
let myString = 'seven'
// 等价于
// let myString: string = 'seven'
// 定义变量时没有赋值,会推断为 any 类型
let myString;
myString = 'seven'
myString = 7

类型断言

告诉ts编译器:“我知道我在干什么,我能确定我现在的这个变量是什么类型”。ts 会假设你已经进行了类型的检查。

function getStrLen(str: number | string) {
  // if(str.length) {  这里ts会因为不确定str是否一定是string而报错,告诉你 类型string|number上不存在length属性
  if((<string>str).length) { // 类型断言str就是string类型(书写方式一)
    return (str as string).length // 两种书写方式(书写方式二)
  } else {
    return str.toString().length
  }
}

console.log(getStrLen('hello'))

类型别名

type Lady = {name: string, age: number} // 对象类型可以使用类型别名
let arr: Lady[] = [
  {name: 'Jane', age: 17},
  {name: 'Jian', age: 20}
]

接口(interface)

// 提供一种方式来定义某种结构,ts按照这种结构来检测数据(跟类型别名有点类型,不同的是接口必须赋值为对象)。
interface Options {
  width: number,
  height: number,
  say(): string // 函数必须返回字符串,无返回值的类型是void
  // color?: string, // 可选
  // [attr: string]: number // key是string类型,value是number类型的属性都可以接受(可以接受多个)
}

function fn(opts: Options) {
  // balabala
}

fn({
  height: 200,
  width: 100,
  say() {
    return 'Jane' // 必须返回 string 类型值
  }
})

类实现接口

可以使用class MyClass implements MyInterface 让某个类实现某个接口

interface IFly{
  fly(): string
}

// YouFly 类中必须有 IFly 接口中定义的 fly 方法,多个接口可以为 class xxx implements kkk,hhh{}
class YouFly implements IFly{
  fly(): string {
    return 'I can fly'
  }
}

接口的继承

interface IFly{
  fly(): string
}

interface ISwim{
  swim(): string
}

interface IFlySwim extends IFly, ISwim{}

属性声明

// ts中的类,成员属性必须要先声明后使用,且在class内方法外声明
// public:公开的,类的内部和外部(实例中)都可以访问,属性和方法默认都是public
// protected:受保护的,在类的内部和他的子类中才能访问,实例中不能访问
// private:私有的,只能在该类的内部才能访问,子类和实例中都不能访问
// readonly:只读,实例不能对这个属性赋值
class Person {
  username: string
  private _age: number
  protected job: string
  constructor(name: string, old: number = 0, living: string) {
    this.username = name
    this._age = old
    this.job = living
  }
}

静态成员

class Person{
  static job: string
  constructor(j: string) {
    // 此时job被static修饰,就是一个静态属性,不能通过this来访问了(this是实例对象)
    // this.job = j
  }
  static sayJob() {
    console.log('I have a job')
  }
}

// static修饰的静态成员(静态属性和静态方法)只能通过类名来调用(不能通过实例对象来调用)
Person.job = 'coder' // 静态属性的修改
console.log(Person.job)
Person.sayJob()

存取器

// 存取器可以对设置的值进行限制
class Person {
  private _age: number = 10

  get age(): number {
    return this._age
  }
  set age(age: number) {
    if(age > 0 && age < 150) {
      this._age = age
    }
  }
}

let p1: Person = new Person()
console.log(p1.age) // 10
p1.age = 300
console.log(p1.age) // 10

抽象类

抽象类不能用来创建对象,就是专门用来被继承的类

// 抽象类(只能被用来继承,不能被实例化new)
abstract class Girl{
  // 抽象方法,抽象方法不能有具体的实现内容
  abstract skill(): void
  // 实例方法
  gender() {
    console.log('female')
  }
}

// 继承自抽象类的类都必须有抽象类中的抽象方法
// 实例方法可以没有
// 实例化后的 const girl = new Girl() 可以直接调用抽象类的实例方法 girl.gender()
class Waiter extends Girl{
  skill() {
    console.log('serve')
  }
}

class Teacher extends Girl{
  skill() {
    console.log('teach')
  }
}

单例案例

class Mysql {
  // 静态属性(不需要通过new出来的对象访问,直接通过类来访问)
  public static instance 

  host: string
  port: number

  // private的构造函数,外部不能通过new来构造对象了
  private constructor(host: string = '127.0.0.1', port: number = 3306) {
    this.host = host
    this.port = port
  }

  public static getInstance() {
  	// 单例,永远只有一个Mysql的实例
    if(!Mysql.instance) {
      // 可以通过内部来创建实例
      Mysql.instance = new Mysql()
    }
    return Mysql.instance
  }

  query() {}
  update() {}
}

let db = Mysql.getInstance()
db.query()

函数

函数类型

JavaScript 中有两种常见定义函数的方式——函数声明(Function Declaration)和函数表达式(Function Expression)。
一个函数有输入和输出,要在 TypeScript 中对其进行约束,需要把输入和输出都考虑到。

// Function Declaration
function sum(x: number, y: string): string {
  return x + y
}
// Function Expression
// 这种情况 = 左侧是通过类型推断出来的
let sum = function (x: number, y: string): string {
  return x + y
}
// Function Expression
// 这种情况 = 左侧是类型指定的
let sum: (x: number, y: string) => string = function (x: number, y: string): string {
  return x + y
}

注意:TypeScript 中的 => 用来表示函数定义,左边是输入类型,用括号括起来,右边是输出类型。跟 ES6 中的 => 箭头函数还是不同的,不要混淆

可选参数

// 参数 y 可选
function sum(x: number, y?: string): string {
  return x + y
}

默认参数

function sum(x: number, y: string = 'Jane'): string {
  return x + y
}

剩余参数

function sum(x: number, ...rest: string[]): string[] {
  return rest.map(i => i + x)
}

函数重载

JavaScript本身是个动态语言。 JavaScript里函数根据传入不同的参数而返回不同类型的数据是很常见的。这怎么在类型系统里表示呢?方法是为同一个函数提供多个函数类型定义来进行函数重载,编译器会根据这个列表去处理函数的调用,重载的函数在调用的时候会进行正确的类型检查。

function fn(x: number, y: number): number
function fn(x: string, y: string): string
function fn(x: string|number, y: string|number): string|number{
  if(typeof x === 'number' && typeof y === 'number') {
    return x + y
  } else if(typeof x === 'string' && typeof y === 'string') {
    return x + '_' + y
  } else {
    return '错误'
  }
}

// 如果没有前两个重载这里不会报错,输出内容是“错误”
// 如果有了前两个重载这里就会报错,因为此时的参数不符合重载函数的任何一种传参数据类型
fn(10, 'kkk')

泛型

泛型函数

// 让函数的参数可以有多种类型,具体什么类型是我们使用的时候决定的
function fn<T>(val: T, count: number): T[]{
  const arr: Array<T> = []
  for(let i = 0; i < count; i++) {
    arr.push(val)
  }
  return arr
}

// 在调用函数fn的时候, 参数是number类型,此时表示变量T赋值为number(因为调用的时候传入的是number)
// 也可以在调用的时候主动设置传入的值的类型
const arr1 = fn<number>(10, 3) // [10, 10, 10]
const arr2 = fn<string>('abc', 2) // ['abc', 'abc']

箭头函数泛型

<T>(contCn: T, contEn: T): T => {
	return contCn || contEn
}

泛型接口

interface IFn<T> {
  (x: T, y: T): number
}
// T就是number了
let fn: IFn<number> = function(x: number, y: number) {
  return Number(x) + Number(y)
}

泛型类

interface Girl{
  name: string
}

class SelectGirl<T extends Girl>{
  constructor(private _girls: T[]) {}
  getGirl(index: number): string {
    return this._girls[index].name
  }
}

new SelectGirl([{name: 'xxx'}, {name: 'kkk'}])

ts 中的 this

默认指向

js中函数的this指向
ts 中默认情况下函数中的 thisany 类型(ts 不能提示任何属性和方法,也就是类型系统没用了…所以我们一般都尽量不使用 any 类型)

let obj = {
  a: 10,
  fn() {
    // this 是 any 类型
  }
}

官方给出的解决方案是:给编译器(tsconfig.json文件)设置 noImplicitThis: true

let obj = {
  a: 10,
  fn() {
    // this 指向obj对象
  }
}

设置this指向

我们也可以强行设置 this 的指向,比如:

let obj = {
  a: 10,
  fn() {
    this // this指向obj对象
  }
}

document.onclick = obj.fn // 期望的函数中的this指向document对象

ts 中函数的第一个参数是用来设置 this 类型约束的(这是一个假参数,没有实际的运行作用,只是用来给 ts 检测使用的)

let obj = {
  a: 10,
  fn(this: Document) {
    this // this指向document对象
  }
}

document.onclick = obj.fn

装饰器

尽可能不改变类结构的情况下,扩展其功能,可以被附加到类声明、属性、方法、参数或访问符上。

// {new()}表示是一个构造函数类型
function Age<T extends {new(...args: any[])}>(constructor: T): T {
  class Person2 extends constructor{
    age: number = 0
  }
  return Person2
}
// Age是一个装饰器函数,会自动调用,不需要()调用,调用的时候会传入下面对应的class的构造函数作为参数
@Age
class Person {
  username: string = 'Jane'
}

let p = new Person()
console.log(p) // Person2 {username: 'Jane', age: 0}
  • 3
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值