ts快速入门

80 阅读7分钟
  • 全局安装
    • npm install -g typescript
  • 接口
    • 一种能力,也是一种约束,有接口的类型会自动提示该类型
//接口:一种能力,也是一种约束
(
  ()=>{
    interface IPerson {
      firstName: string
      lastName: string
    }
    function showFullName(person:IPerson){
      return person.firstName + person.lastName
    }
    const person = 
    {
      firstName:'东方',
      lastName: '不败'
    }
    showFullName(person)
  }
)()
    • 接口同样可以约束类
(()=>{
  interface IPerson{
    firstName:string
    lastName:string
  }
  //定义一个类型
  class Person {
    //定义公共字段
    firstName:string
    lastName:string
    fullName:string
    //定义一个构造器函数
    constructor( firstName:string,lastName:string){
      //更新属性
      this.firstName = firstName
      this.lastName = lastName
      //姓名
      this.fullName = this.firstName+'_'+this.lastName
    }

  }
  //定义函数
  function getFullName(person:IPerson){
    return person.lastName + '_'+person.firstName
  }
  getFullName(new Person('诸葛','孔明'))
})()

基本类型

  • 布尔(boolean)
let flag:boolean = false
console.log(flag)	
  • 数字
    • 和 JavaScript 一样,TypeScript 里的所有数字都是浮点数。 这些浮点数的类型是 number。 除了支持十进制和十六进制字面量,TypeScript 还支持 ECMAScript 2015中引入的二进制和八进制字面量。
let a1: number = 10 // 十进制
let a2: number = 0b1010  // 二进制
let a3: number = 0o12 // 八进制
let a4: number = 0xa // 十六进制
  • 字符串
(
  function getString() {
    let name: string = 'tom'
    name = 'jack'
    // name = 12 // error
    let age: number = 12
    name = name+age
    const info = `My name is ${name}, I am ${age} years old!`
  }

)()
  • undefined 和 null
    • TypeScript 里,undefined 和 null 两者各自有自己的类型分别叫做 undefined 和 null。 它们的本身的类型用处不是很大:
let unde:undefined = undefined
let nul:null = null
  • 数组有两种定义方式
    • 直接后面接[]
    • 或者利用数组泛型
let arr1:number[] = [1,2,3]
let arr2:Array<number> = [1,2,3]  
  • 元组
    • 元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string 和 number 类型的元组。
 let t1:[string,number]
 t1 = ['hello',10]
  • 枚举
    • 枚举赋值
enum Color {
  red,
  green,
  blue
}

let color:Color = Color.red
  • 枚举自动编号
enum Color {
  red=1,
  green,
  blue
}

let c:Color = Color.green
console.log(c)  //2
  • 由枚举值得到枚举名
enum Color {
  red=1,
  green,
  blue
}

let c:Color = Color.green
console.log(Color[2])   //green
  • any
    • 如果不确定变量类型,又想令其通过检查,可以用any
let num:any
num = 2
num = 'sx'
  • void
    • 表示没有任何类型
      • 当函数没有返回值时可以用void
      • 定义void类型变量没有意义,因为只能赋值undefined和null
function my():void {
  console.log('sx')
}

let numsx:void = undefined
  • object
    • 非原始类型
function myObject(ob:object):object {
  return {}
}
  • 联合类型
    • 联合类型(Union Types)表示取值可以为多种类型中的一种
function Un(x:number | string) :object {
  x.toString()
  return {}
}
  • 断言
    • 通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。 TypeScript 会假设你,程序员,已经进行了必须的检查。
    • 类型断言有两种形式。 其一是“尖括号”语法, 另一个为 as 语法
function ase(x:number|string):number{
  //断言成string类型
  if((<string>x).length){
    return (x as string).length
  }
  else {
    return x.toString().length
  }
}

接口

  • TypeScript 的核心原则之一是对值所具有的结构进行类型检查。我们使用接口(Interfaces)来定义对象的类型。
  • 接口: 是对象的状态(属性)和行为(方法)的抽象(描述)
interface Person {
  readonly id:string, //可读属性,初始化后不可修改
  name:string,
  age:number,
  sex?:string //可选属性
}

const person1:Person = {
  id:'1',
  name:'sx',
  age:18,
  sex:'男'
}
  • 函数类型
    • 接口能够描述 JavaScript 中对象拥有的各种各样的外形。 除了描述带有属性的普通对象外,接口也可以描述函数类型。
    • 为了使用接口表示函数类型,我们需要给接口定义一个调用签名。它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型。
interface myFn {
  (x:number,y:string):boolean
}

const myF:myFn = function(age:number,name:string){
  return false
}
  • 类类型
    • 一个类可以实现多个接口
interface Alarm{
  alert():any
}

interface Light {
  lingtOn():any;
  lightOff():any;
}
class Car implements Alarm,Light{
  alert() {
    
  }
  lingtOn() {
    
  }
  lightOff() {
    
  }
}
  • 接口也可以继承接口
interface Alarm{
  alert():any
}

interface Light {
  lingtOn():any;
  lightOff():any;
}

interface AlarmAndLight extends Alarm,Light{}
class Car implements AlarmAndLight{
  alert() {
    
  }
  lingtOn() {
    
  }
  lightOff() {
    
  }
}

  • es6之后,可以使用类的面向对象的方式
class Mes{
  message:string
  constructor(mes:string){
    this.message = mes
  }
  sayMes(){
    console.log(this.message)
  }
}

const myMes = new Mes('sx')
myMes.sayMes()
  • 类的继承
class Anamial{
  run(distance:number){

  }
}

class Dog extends Anamial{
  cry(){

  }
}

let dog = new Dog()
dog.cry()
dog.run(100)
  • 类的属性类型
    • public:默认公开,子类,实例都可访问
    • private:私有,子类,实例都不可访问
    • protected:保护,子类可访问,实例不可访问
class Anamial{
  public name:string
  protected age:number
  private sex:string
  constructor(name:string,age:number,sex:string){
    this.name = name
    this.age = age
    this.sex = sex
  }
}

class Dog extends Anamial{
  run(){
    console.log(this.age)
  }
}

let dog = new Dog('sx',18,'s')
dog.name
dog.run()	
  • readonly修饰符
    • readonly 关键字将属性设置为只读的。 只读属性必须在声明时或构造函数里被初始化
class Person {
  readonly name: string = 'abc'
  constructor(name: string) {
    this.name = name
  }
}

let john = new Person('John')
// john.name = 'peter' // error
  • 参数属性
    • 上述我们必须在 Person 类里定义一个只读成员 name 和一个参数为 name 的构造函数,并且立刻将 name 的值赋给 this.name,这种情况经常会遇到。 参数属性可以方便地让我们在一个地方定义并初始化一个成员。 下面的例子是对之前 Person 类的修改版,使用了参数属性:
class Person2 {
  constructor(readonly name: string) {
  }
}

const p = new Person2('jack')
console.log(p.name)
  • 存取器
    • 存取器在对属性进行取值和赋值的同时可以添加更多的操作,如类型判断
class Name {
  constructor( private firstName:string,private lastName:string){
    this.firstName = firstName
    this.lastName = lastName
  }
  get fullName(){
    return this.firstName+'_'+this.lastName
  }
  set fullName(value:string){
    const names = value.split('_')
    this.firstName = names[0]
    this.lastName = names[1]
  }
}

const xiaoming = new Name('西门','吹雪')
console.log(xiaoming.fullName)
xiaoming.fullName = 's_x'
console.log(xiaoming.fullName)

  • 静态属性
    • 静态属性可以在类上直接访问
class Name{
  static names:string = 'sx'
}

console.log(Name.names)
  • 抽象类
    • 抽象类做为其它派生类的基类使用。 它们不能被实例化。不同于接口,抽象类可以包含成员的实现细节。 abstract 关键字是用于定义抽象类和在抽象类内部定义抽象方法。
abstract class Anamial{
  abstract cat()
  run(){
    console.log('run')
  }
}

class Dog extends Anamial{
  cat(){
    console.log('cat')
  }
}

函数

  • 函数可以分为匿名函数和命名函数
  • 函数默认参数和可选参数

泛型

  • 当我们定义一个变量不确定类型的时候有两种解决方式:
    • 使用any
      • 虽然知道传入值的类型但是无法获取函数返回值的类型,ts类型保护机制也失去意义
    • 泛型
      • 定义函数、接口时,不预先指定具体类型,而是使用的时候指定类型限制
function add<T>(arg:T):T{
  return arg
}

add<string>('sx')
add<number>(1)
  • 在接口中使用泛型
interface Search{
  <T,Y>(x:T,y:Y):T
}

let fn:Search = function<T,Y>(x:T,y:Y):T{
  return x
}

fn(123,'sx')
interface Anamial1<T>{
  data:T[],
  add(use:T):void
  getId(id:number):T
}

class User{
  constructor(public name:string,public id:number,public data:string){}
}

class Cat implements Anamial1<User>{
  data:User[] = []
  add(use: User): void {
    this.data.push(use)
  }
  getId(id: number): User {
    return this.data.find(u => u.id == id)
  }
}

let cat = new Cat()

cat.add(new User('sx',1,'10'))
cat.getId(1)
  • 泛型约束
    • 如果我们直接对一个泛型参数取 length 属性, 会报错, 因为这个泛型根本就不知道它有这个属性
    • 通过泛型约束来实现,传入的参数必须拥有这个约束
function fn<T>(x:T){
  //这里会报错,x不知道自己有length属性
  console.log(x.length)
}
interface hasL {
  length:number
}

function fn<T extends hasL>(x:T){
  console.log(x.length)
}

声明文件

  • 当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全、接口提示等功能
  • 假如我们想使用第三方库 jQuery,一种常见的方式是在 html 中通过
  • 但是在 ts 中,编译器并不知道 $ 或 jQuery 是什么东西
  • 这时,我们需要使用 declare var 来定义它的类型
declare var jQuery: (selector: string) => any;

jQuery('#foo');