初识TS

// ts声明简单类型
let number: number = 4
let str: string = '4'
let bool: boolean = true
let u: undefined = undefined
// 报错 不能将u赋值为string类型
// u = 's'
// undefined和null是所有类型的子类型
str = undefined

let n: null = null
// 报错 不能将n赋值为string类型
// n = '4'
// undefined和null是所有类型的子类型
u = n
let any: any = '4'
any = true
any = '4'
any = 3
any = undefined
any = null


// ts声明复杂类型---------》数组
let arr: any[] = [1,2,3,'4']      // 任意数组
let arr1: number[] = [1,2,3,]     // 纯数字类型的数组
let arr2: string[] = ['1', '2']   // 纯字符串类型的数组


// ts 声明复杂类型---------》元组

let arr3: [string, number] = ['1', 5]
// 报错 不能将类型“[string, number, number]”分配给类型“[string, number]”。  源具有 3 个元素,但目标仅允许 2 个
// let arr4: [string, number] = ['1', 5, 5]

// 在使用数组的一些方法时,如push只能push已声明的类型 否则报错
arr3.push('456')
arr3.unshift(5)


// ts声明复杂类型--------》接口 interface
interface Person {
  name: string,
  age: number,
  sex: string,
}
// user里面的属性必须和Person里面声明的属性保持一致(多少都不行),否则报错
let user : Person = {
  name: '蔡徐坤',
  age: 30,
  sex: '女'
}
// 在接口中定义可选参数
interface Person1 {
  name: string, // name 为必选参数
  age?: number, // age? 为可选参数
  sex?: string,// sex? 为可选参数
}
let user1 : Person1 = {
  name: '蔡徐坤', // 如果不传则报错
}
// 在接口中定义只读属性
interface Person2 {
  name: string
  readonly id: number
}
let user2: Person2 = {
  name: '蔡徐坤',
  id: 2
}
// user2.id = 5 报错


// 泛型(类似占位符<>)
// 定义函数、接口和类的时候,先不设定类型,等到使用的时候才定义类型
function echo<T>(arg: T) :T {
  return arg
}
const res = echo(123)

function swap<T, U>(arr:[T,U]):[U, T]{
  return [arr[1], arr[0]]
}
const result = swap([123, 'str'])

const changeVal = <T>(val: T) => {}
changeVal<number>(9)
const changeVal: <T>(val: T) => T = (val) => {
  console.log(val)
  return val
}
changeVal<number>(9)
function changeV<T>(val: T) {}
changeV<string>('9')
function changeV<T>(val: T):T {
  return val
}
changeV<string>('9')
// 泛型的约束
// 目的:只想返回一个具有length属性的函数
// function getLength<T>(length: T): T {
  // 报错,因为不一定变量length中有length属性,此时使用泛型约束
  // return length.length
// }
interface length {
  length: number
}
function getLength<T extends length>(length: T): T {
  return length
}
getLength('123')
getLength([1,2,3])
getLength({length: 50, name: '12313'})

// 在类中使用泛型
class Queue<T> {
  private data = []
  push(item: T) {
    return this.data.push(item)
  }
  pop():T {
    return this.data.shift()
  }
}
const queue = new Queue<number>()
queue.push(1)
// 报错,不能push字符串
// queue.push('123')
// 编译时会报错,因为数字没有toFixed方法,此时ts检测不出来
console.log(queue.pop().toFixed());

interface keyPair<T, U> {
  key: T,
  value: U
}
const key:keyPair<number, string> = {key:1, value: '123'}
const key2:keyPair<string, number> = {key:'4564', value: 123}
// 两种写法等价
const arr_: number[] = [123, 456,]
const arr__: Array<number> = [123, 456]

// 字面量 只能是原始类型,赋值其他会报错
const strName: 'name' = 'name'

// 类型别名 type
type P = 'left' | 'right' | 'top' | 'down'
const position9: P = "right"
// 联合类型 |
const or = 'left' | 'right' | 'top' | 'down'
// 交叉类型 &
interface Inum {
  num: number
}
type InumAndString = Inum & {name: string}
const nameLiu: InumAndString = {name:'xxx',num:4}


// ts函数(参数类型和返回值类型)如果不返回默认是void
function fn(x: number, y: number):number {
  return x + y
}
fn(4, 5)
// 传递为对象,对象里面的参数限制
function count (a:{a:number,b:number}){
  console.log(a);
}
count({a:2,b:5})
// 下面两种写法等价(接口定义函数和函数类型)
interface Ifn {
  (x:number, y:number): number
}
const fn1:Ifn = function fn(x: number, y: number):number {
  return x + y
}
const myFn :(x:number, y:number) => number = function (x:number, y:number):number {
  return x + y
}
// 类型推断(上面的fn函数,如果fn函数返回值省略,ts会根据类型推断出fn返回的是number类型)

// enum 枚举类型 默认是0开始,也可以自定义,枚举的每一个值都是唯一的。
enum Color {
  red,
  green,
  blue
}
const color = Color.red // color值为1
// 数字枚举
enum Color1 {
  red = 10,
  green = 20,
  blue = 30
}
const color1 = Color1.red // color值为10
// 枚举支持反推,当我们明确枚举某个值时,能反推出key值(例:)
const colorKey = Color1[20] // colorKey为green

// 字符串枚举 如果字符串枚举对值进行初始化,则必须每个都要初始化,不然ts会报错
enum Directions {
  UP = 'up',
  Down = 'down',
  Left = 'left',
  Right = 'right'
}

// 总结
// interface 定义接口,(object类型)
// enum 定义枚举类型
// type 定义类型别名
// as 类型断言
function getLengthFn (value: number | string) :number{
  const str = value as string
  if (typeof str === 'string') {
    return str.length
  } else {
    const num = value as number
    return num.toString.length
  }
}
// 或直接用typeof检测类型
function getLengthFn1 (value: number | string) :number{
  if (typeof str === 'string') {
    return str.length
  } else {
    return value.toString.length
  }
}


// 如何检查getProperty(x, "m")的报错(核心keyof:keyof该操作符可以用于获取某种类型的所有键,其返回类型是联合类型 )
function getProperty(obj, key :keyof IGetProperty):string {
  return obj[key].toString();
}
interface IGetProperty {
  a:number,
  b:number,
  c:number,
  d:number
}
let x:IGetProperty = { a: 1, b: 2, c: 3, d: 4 };

getProperty(x, "a");
getProperty(x, "m");
//或者
function getProperty<T extends object, U extends keyof T>(obj: T, key :U):string {
  return obj[key].toString();
}
const x = { a: 1, b: 2, c: 3, d: 4 };

getProperty(x, "a");
getProperty(x, "m");
// 定义一个空对象,且对空对象后期赋值的对象约束
import { ref } from 'vue';
interface MyObject {
  name: string;
  age: number;
}
// 使用 Partial 让属性可选
const myObject = ref<Partial<MyObject>>({});
// 后续赋值时可以选择性地赋值
myObject.value = { name: "xxx" }; // 正确
myObject.value = { age: 1 }; // 正确
posted @ 2021-12-31 14:54  Life_countdown  阅读(149)  评论(0)    收藏  举报