TypeScript

// 普通数据类型
var msg: string = "Hello Ts"
console.log(msg);
// 定义只能存放number类型的数组
var numsList: number[] = [1, 2, 3]
var numsList1: Array<number> = [1, 2, 3]
// 定义既能存储number类型又能存储string类型的数组
var arr: (number | string)[] = [1, 2, 3, '1']
// 解释 | 在ts中叫做联系类型(有两个或者多个其他类型组成的类型,表示可以是这些类型中的任意一种
var arr1: Array<number | string> = [1, 2, '2']

// 类型别名 
type custoArry = Array<number | string>
// 使用type关键字来创建类型别名 类型别名可以是任意的合法的变量名
// 创建类型别名后,直接使用该类型别名作为变量的类型的注解
// 用类型别名定义的类型可以是任意的类型
var arr2: custoArry = [1, 2, 'hello']

// 函数类型
// 1.给函数的参数定义类型
// 2.给函数的返回值定义类型

// 单独指定参数和返回值类型
function add(num1: number, num2: number): number {
    return num1 + num2
}
console.log(add(1, 1));

// 同时指定参数和返回值类型
const add2: (num1: number, num2: number) => number = (num1, num2) => {
    return num1 + num2
}
console.log(add2(1, 1));
// 这种形式只适用于函数表达式
// 但函数作为表达式时,可以通过类似箭头函数的语法为函数添加类型
// 如果一个函数没有返回值,那么函数的返回值为void
function greet(name: string = 'zs'): void {
    console.log('name:' + name);
}
greet()

// 可选参数
function myslice(start?: number, end?: number): void {
    console.log(start + ":" + end);

}
// 注意可选参数必须放在最后
myslice(1)
// 对象类型
let person: { name: string; age?: number; sayh(): void } = {
    name: 'zs',
    age: 18,
    sayh() {

    },
}


// 接口
interface Iperson {
    name: string
    age: number
    sayhello: (msg: string) => void
}

var person1: Iperson = {
    name: 'zs',
    age: 18,
    sayhello(msg: string) {
        console.log(msg
        );

    }
}
// 使用interface声明接口
// 接口的名字可以是任意合法的变量名
// 声明接口之后,可以直接使用接口的名称作为变量的类型

interface Iperson1 extends Iperson {
    saygoodbye: () => void
}

var zs: Iperson1 = {
    name: 'zs',
    age: 10,
    saygoodbye() {
        console.log('goodbye');
    },
    sayhello(msg: string) {
        console.log(msg);
    }
}

// 通过extends实现接口的继承
// 接口Iperson1就有了Iperson所有的属性和方法

// 元组
let position: [number, string] = [1, '2']


// 类型推论
// ts中,某些地方没有明确的指出类型的地方,ts的类型推论机制就会帮助提供类型
// 某些地方可以不写类型注解,由于有类型推论机制的存在
// 应用场景:
// 1.变量声明时,如果没有明确的类型注解,ts会根据变量的值推断出变量的类型
// 2.函数有返回值时

// 字面量类型
let str3 = 'hello TS'
const str4 = 'HELLO TS'

function changeDirection(direct: 'up' | 'down' | 'left' | 'right') {
    console.log(direct);

}

changeDirection('down')

// 枚举
enum Direction {
    Up = 'up',
    Down = 'down',
    Left = 'left',
    Right = 'right'
}
function changeDirection1(direct: Direction) {
    console.log(direct);
}

changeDirection1(Direction.Up)
changeDirection1(Direction.Down)
changeDirection1(Direction.Left)


// any类型 失去ts类型保护
let obj: any = { x: 0 }
obj.bar = 100
obj = () => {

}

// typeof
// js中就有typeof得到变量的类型
// ts中的typeof,可以在类型上下中引用变量或者属性的值(类型查询)
// 使用场景:根据已有的变量的值,获取该变量的类型,简化类型书写。
let p = { x: 1, y: 2 }
function formateDate(obj: typeof p) {
    console.log(obj.x, obj.y);

}
formateDate({ x: 1, y: 1 })

// ts高级类型
// class
// 实例属性
class Person {
    age: number
    name: string
    constructor(age: number, name: string) {
        this.age = age;
        this.name = name
    }
}

// 实例方法
class Point {
    x = 10
    y = 10
    scale(n: number): void {
        this.x *= n
        this.y *= n
        console.log(this.x, this.y);
    }
}
// 解释
// 1、成员初始化(age,name)后,才可以通过this.age来访问实例的成员
// 2、构造函数不需要返回值的类型

// 类的继承

// 类的继承分为两种:1.extends(继承父类) 2.implements(接口实现)
// 说明:js中只有extends implements是ts中提供的
class Animal {
    move() {
        console.log('moving along');
    }
}

class Dog extends Animal {
    bark() {
        console.log('狗叫');
    }
}
const dog = new Dog()
dog.bark()
dog.move()
// 类实现接口
interface Singbale {
    sing(): void
}
class Person1 implements Singbale {
    sing(): void {

    }
}

// 类成员的可见性
// 可以使用ts来控制class 的方法或者属性对于class外面的代码是否可见(能不能访问到)
// 可见性修饰符
// 1.public 公有(默认) 公有成员在任何位置都可以访问到
// 2.protected 受保护
// 3.private 私有

class Animal1 {
    readonly age: number = 10
    constructor(age: number) {
        this.age = age
    }
    public move(): void {
        console.log('moving');

    }
    protected say(): void {
        console.log('叫');
    }
}

const a = new Animal1(20)
a.move()

class Dog1 extends Animal1 {
}
const d = new Dog1(30)
console.log(d.age);
// d.age=20


// 解释
// 在类的属性或者方法的前面加上public关键字,可以表示这个属性或者方法是公有的
// 但是因为默认的可见性修饰符为public,所以public关键字可以省略
// protected 受保护的,仅可在类和其子类中使用,实例方法均不能调用
// private 私有的,只在当前的类可见,对实例对象以及子类不可见
// readonly 只读修饰符 只能用于属性 。用来防止在构造函数外面修改属性


// 类型兼容性
// 两种类型系统
// 1.结构化类型系统
// 2.标明类型系统
// Ts采用的是结构化类型系统(鸭子系统)类型检查关注的是值具有的形状(属性或者方法)
// 如果俩个对象具有相同的形状,则认为他们属于同一类型

class Test1 {
    x: number
    y: number
    constructor(x: number, y: number) {
        this.x = x
        this.y = y
    }
}


class Test2 {
    x: number
    y: number
    constructor(x: number, y: number) {
        this.x = x
        this.y = y
    }
}
class Test3 {
    x: number
    y: number
    z: number
    constructor(x: number, y: number, z: number) {
        this.x = x
        this.y = y
        this.z = z
    }
}
// 俩个对象具有相同的形状,则认为他们属于同一类型
const test1: Test1 = new Test2(10, 20)
// 结构化类型,成员多的可以赋给成员少的
const test2: Test1 = new Test3(10, 20, 30)
console.log(test2);

// Ts中的其他类型也存在相互兼容的情况
// 1.接口兼容性
// 2.函数兼容性

// 接口兼容性类似于class,class和interface可以相互兼容
interface Test4 {
    x: number
    y: number
}
interface Test5 {
    x: number
    y: number
}
interface Test6 {
    x: number
    y: number
    z: number
}
let p1: Test4 = { x: 1, y: 1 }
let p2: Test5 = { x: 1, y: 1 }
let p3: Test6 = { x: 1, y: 1, z: 1 }
// 成员多的赋给成员少的
p1 = p2
p2 = p1
p1 = p3
// 错误
// p3=p1 

let p4: Test5 = p1
p4 = p3

// 函数之间的兼容性
// 需要考虑:1.参数的个数 2.参数的类型 3.返回值的类型
// 参数多的兼容参数少的(参数少的赋值给多的)

type F1 = (a: number) => void
type F2 = (a: number, b: number) => void

let f1: F1 = (a: number) => {
    console.log(a);
}

let f2: F2 = f1
// 解释
// 1.参数少的可以赋值给参数多的,发f1可以赋值给f2
// 2.返回值类型,只关注于返回值的类型就可以了

type F3 = () => { name: string }
type F4 = () => { name: string, age: number }

let f3: F3 = () => {
    return { name: "zs" }
}

let f4: F4 = () => {
    return { name: "zs", age: 19 }
}
f3 = f4

// 交叉类型
// 对象类型如何定义
// 接口定义类型
// interface mycustom{
//     name:string
//     age:number
// }
// type定义类型
type mycustom = {
    name: string
    age: number
}

var obj1: mycustom = {
    name: 'zs',
    age: 10
}

interface User {
    name: string
}

interface Contact {
    phone: string
}

type PersonDetails = User & Contact

let user: PersonDetails = {
    name: "sk",
    phone: '1111111'
}

interface A {
    fn: (value: number) => string
}

interface B extends A {

}
let obj2: B = {
    fn: (value: number) => "hello"
}

// 泛型
// 在保证类型安全的前提下,让函数于多种类型一起工作,从而实现复用
// 常用于函数 接口 类
// 创建泛型函数的语法
function fn1<T>(value: T): T {
    return value
}
fn1<string>('a')
fn1<number>(1)

// 解释
// 1.语法:函数的名称的后面<添加了类型的变量>,这里是T
// 2.类型变量T一种特殊的变量,它处理的是类型而不是值
// 3.类型变量相当于类型容器,它能够获取用户提供的类型
// 4.因此,可以将T作为参数和返回值的类型,表示参数和返回值具有相同的类型
// 5.T可以是任何的合法的变量名
// 调用泛型函数
// 方法名称<具体的数据类型>()

// function fn2<T>(value:T):T{
//    console.log(value.length);
//     return value
// }

// fn2<string>("111")
// T可以为任意类型,但不是所有类型都有length属性,故fn2会报错
// 泛型约束,默认情况下,泛型函数的类型变量代表多个类型,这就导致无法保证无法访问任何的属性
// 此时,就需要给泛型添加约束来收缩类型

// 添加泛型约束来收缩类型,主要有两种方式
// 1.指定更加具体的类型
// 2.添加约束

// 1.指定更加具体的类型
// function fn3<T>(value: T[]): T[] {
//     console.log(value.length);
//     return value
// }
// fn3([1, 2, 3, 4, 5])
// 比如,将类型
// 2.添加约束
// type Ilength={ length: number }
// // interface Ilength{length:number}

// function fn4<T extends Ilength>(value:T):T{
//     console.log(value.length);
//     return value
// }
// fn4([1, 2, 3, 4, 5])
// fn4('12313')
// fn4(1111)
// number类型无length属性,故报错

// 解释
// 1.创建了一个描述约束的接口,里面有length属性。
// 2.通过extends继承了该接口,给这个T添加了约束
// 3.该约束表示:传入的属性必须具备length这个属性


// 泛型的变量可以有多个,并且类型变量之间可以相互的约束(如:第二个类型变量
// 受到第一个类型变量的约束)
let person4 = { name: 'jack', age: 18 }
function getProp<T1, T2 extends keyof T1>(obj: T1, key: T2) {
    return obj[key]
}

getProp(person4, 'name')
getProp(person4, 'age')

// 解释:
// 1.添加了第二个类型变量T2
// 2.keyof关键字 接收一个对象类型,生成其'键'名的联合类型
// 3.keyof T1 获取person4对象中的所有的键名的联合类型,也就是"name" |"age"
// 4.类型变量T2受到T1的约束,T2只能是T1所有键中的任意一个



// 泛型接口:接口也可以配合泛型来使用,实现复用
// 接口中所有的成员都可以使用类型变量
interface IdFunc<T> {
    id: (value: T) => T
}

let obj3: IdFunc<string> = {
    id(value) { return value }
}

// 解释
// 1.接口的名称后面<>,就变成了泛型接口
// 2.接口的白能量对接口的成员可见
// 3.使用泛型接口的时候,可以指定具体的类型
// 补充:js中的数组在ts中就是一个泛型接口

// 泛型类,class中也可以配合泛型使用
class GenercNumber<T>{
    defaultValue: T
    constructor(value: T) {
        this.defaultValue = value
    }
}

new GenercNumber(22)

// 泛型工具类型:ts内置了一些常用的工具类型,来简化ts的常见的操作
// 说明:它们都是基于泛型实现的,可以在代码中直接使用
// 1.Partial<Type>
// 2.Readonly<Type>
// 3.Pick<Type>
// 4.Record<Keys,Type>


// Partial<Type>:用来创建一个类型,将type中的所有属性设为可选
// interface Props{
//     id:string
//     children:number[]
// }
// 将Props所有的类型设置为可选,返回新的类型
// type PartialProps =Partial<Props>
// 解释:创建的新的类型PartialProps结构和Props的结构一致,但是它的所有属性都是可选的。


// Readonly<Type>: 用来创建一个类型,将type中的所有属性设为只读
// interface Props{
//     id:number
//     children:number[]
// }
// 将Props所有的类型设置为只读,返回新的类型
// type ReadonlyProps =Readonly<Props>
// let obj4:ReadonlyProps={
//     id:123,
//     children:[1,23,1]
// }

// obj4.id=2123

// Pick<Type>:从type中选择一组属性来创建新的类型
// interface Props{
//     id:string
//     title:string,
//     children:number[]
// }

// type PickProps=Pick<Props,'id'|'title'>
// let obj4:PickProps={
//     id:"2222",
//     title:"22222"
// }

// Record<Keys, Type>:创建一个新的类型,属性键名为keys,属性类型为Type
// type RecordObj = Record<"a"|"b" |"c",string[]>

// let obj4:RecordObj={
//     a:["1"],
//     b:["3"],
//     c:["2"]
// }
// Record 有两个类型变量,第一个类型变量指的是对象有哪些属性,
// 第二个类型变量指的是对象属性值的类型


// 索引签名类型
// 使用场景:当我们无法确定对象中有哪些属性的时候
// interface  AnyObject{
//     [key:string]:number
// }

// let  obj5:AnyObject={
//     a:1,
//     b:2,
//     c:3
// }

// 解释
// [key:string]来约束接口中,允许出现的属性的名称,表示只要是string类型的属性名称,
// 都可以出现在这个对象中
// key只是一个占位符,只要是任意合法名称都可以

// JS数组是一类特殊的对象,特殊在数组的索引是数字类型
// var arr3:number[] =[1,2,3,6,1,1];
// 数组可以出现任意多个元素,所以在数组对应的泛型接口中,也用到了索引签名类型
// 数组(泛型 泛型的基础上就加上了索引签名类型)

// interface myArray<T>{
//     [n:number]:T
// }
// let arr4:myArray<number>=[1,2,3]
// let arr5: Array<number> =[1,2,3]
// 解释
// 1. myArray模拟了原生的数组的接口,[n:number]:用作索引签名类型
// 2. 下标只要是number类型就可以(数组中可以出现任意多个元素)

// 映射类型 
// 基于旧的类型创建新的类型, 目的复用
// 比如:类型 Propskeys 有 x y z
// Type1中也有x y z,并且Propskeys和Type1中xyz类型相同
// 如果是这种情况下,可以使用映射类型

// type Propskeys="x" | "y" |"z"
// type Type1 ={x:number;y:number;z:number}
// 以上代码都有x y z且 x y z的类型相同
// 上面的代码没有问题,x y z重复写了两遍
// 就可以使用映射类型

// type Propskeys = 'x' | 'y' | 'z'
// type Type1={[key in Propskeys]:number}
// 解释
// 1.映射类型基于索引签名类型,只要key位置上面有[]肯定是用到了索引签名类型
// 2.key in Propskeys 表示Propskeys联合类型的任意一个,类似于for(let k in Propskeys)
// 注意:
// 映射类型只能在类型别名(自定义类型)中使用,不能在接口总使用

// type Propskeys = {a:number;b:number;c:boolean}
// type Type1 = { [key  in keyof Propskeys]: number }

// 解释
// 1.keyof Propskeys 获取对象中的Propskeys中的所有的属性名'a'|'b'|'c'
// 2.
// 泛型工具类型都是基于映射类型实现的
// Partial<Type>
// type Partials<T>={
//     [P in keyof T]?:T[P]
// }
// type Props = { a: number; b: number; c: boolean }
// type newProps = Partials<Props>

// 解释
// 1.keyof T 表示Props中的所有的属性名'a|'b'|'c'
// 2.[]?表示属性是可选的
// 3.T[P]获取属性名的类型,比如a:number类型
// T[P]:索引查询类型,用来查询属性的类型
type Props = { a: number; b: number; c: boolean }
// type Ta= Props['b']

// 索引查询类型可以同时查询多个属性的类型
type Ta = Props['a'|'c']

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值