美文网首页
数据类型

数据类型

作者: 静小弟 | 来源:发表于2020-03-10 21:41 被阅读0次

typescript

命令

​ tsc --init 生成配置文件

{'compilerOptions': {
    'target': 'es5',
    'module': 'commonjs',
    'strictNullChecks': true // 是否严格null检查,为true,undefined和null不为基础数据类型的子集
}}
scripts:{
    'build': 'tsc'
    'start': 'tsc--watch'
}

ts的基础数据类型

特殊数据类型

数组

1.长度任意

2.类型必须统一

let names:string[] = ['a', 'b', 'c']
let names2: Array<string> = ['a', 'b', 'c'] // 泛型写法

元组

1.长度和类型都确定的数组

let persong:[string, number, string] = ['zhufeng', 10, 'male']
console.log(person[0].length)
console.log(person[1].tofixed(2))
console.log(person[2].length)

枚举类型

enum Gender {
    BOY,
    GIRL
}
let boy: number = Gende.BOY  // 0

常量枚举

const enum Colors {
    RED,
    YELLOW,
    BULE
}
let colors= [Colors.RED, Colors.YELLOW, Colors.BULE] // [0,1,2]

Any 任意类型

let x:any

never 类型

1.作为没有返回值的函数的返回值类型

function get():never {
    console.log(1)
    throw new Error('报错了')
}

never和void的区别

  • void可以被赋值为null和undefined的类型。never则是一个不包含值的类型

  • 拥有void返回值类型的函数能正常运行。拥有never返回值类型的函数无法正常返回,无法中止,或者抛出异常

包装类

基本数据类型是没有方法的

let name1 = 'zhufeng'
// -----------------------------
new String('zhufeng').toLocleLowweCase()
// -----------------------------
let hasGirl:boolean = true
hasGirl = Boolean(true)
hasGirl = new Boolean(true) // 这里是错误的,基本数据类型内置已经帮我们转了对象,所以不能用对象进行复制

当你在一个基本数据类型上调用方法时,会立刻隐含的把一个基本数据类型包装成对象

联合类型

let name: string | number
name = 'zhufeng'
name = 10

类型断言

let name: string | number
name = 'zhufeng'
name = 10
(name as tring).length
function getName(val: string|number|boolean) {
    (val as string).length
}

type

// type 用来定义类型别名
// 函数表达式
type GetUserName = (x:string, y:string) => string
let getUserName: GetUserName = function(firstName, lastName):string {
    return firstname+lastname
}

// 可选参数 加上问号
let items:number[] = [1,2,3,4]
type IteratorFun = (item:number, index?:number, arr?:number[]) => void
let iteratorFun:IteratorFun = function(item:number, index:number, arr:number[]) {}
item.forEach(iteratorFun)

// 默认参数
function ajax(url:string, methods:string="GET"){
    
}
ajax('/user')

// 剩余参数
function sum(prexfix: string, ...args:number[]) {
    return prefix+arg.reduce((val, item) => val+=item,0)
}
let r = sum('$', 1,2,3,4)

// 类型的重载
type MyType = string|number|boolean
function getType(val:MyType):MTtype {
    return val
}

// 函数的重载
function double(val:string): string
function double(val:number): number
function double(val:boolean):boolean 
function double(val:any) {
    if (typeof val === 'string') {
        return val+val
    }
    if (typeof val === 'number') {
        return val*2
    }
    if(typeof val=== 'boolean') {
        return val
    }
}

// get name
class Person1 {
    myname: string,
    constructor(myname:string){
       this.myname = myname
    }
get name() {
    return this.myname
}
set name(val) {
    this.myname = val
}
}
let p1 = new Person1()
p1.name

参数的属性

// 加上public 之后相当于给当前的实例增加一个公有属性
// public priviate protected
class Person2 {
    constructor(public myname:string){
        
    }
}

// readonly 只读 参数不可改
class Person4{
    public readnoly id:number
    constructor(id:number) {
        this.id = id
    }
}

class Parent {
    public name:string; // 公有的name属性,所有地方都能访问
    protected age:number; //  受有限度的保护的属性,只能在自己或自己的子类中被访问
    priviate money:number; // 私有属性,只能自己访问,连自己的子类都不能访问
    constructor(name:string, age:number, money:number) {
        this.name = name
        this.age = age
        this.money = money
    }
    getName() {
        console.log('a', this.name)
    }
    getAge() {
        console.log('a', this.age)
    }
    getMoney() {
        console.log('a', this.money)
    }

}

class Child extends Parent {
    getName() {
        console.log('b', this.name)
    }
    getAge() {
        console.log('b', this.age)
    }
    getMoney() {
        console.log('b', this.money)
    } // 在这里已经报错不能访问了
}

let c = new Child('zfpx',10,100)
c.getName() // 可以正常访问
c.getAge() // 只能在子类中访问,这里是实例
c.getMoney() // 只能在自己中访问

静态属性

// 普通类
class Father {
    static myname:string = 'zhufeng'
    static getMyName() {
        return Father.myname
    }
}
console.log(Father.name)
Father.getMyName()

// 抽象类 abstract
// 抽象类是一种抽象的概念,无法被实例化,只能被继承
// 抽象类里的方法是抽象的
// 重写 父类是一样 子类重写父类逻辑 子类重写竭诚父类中的方法
// 重载 同一个函数提供多个类型定义
abstract class Animal {
    name:string;
    abstract speak()
}

class Cat extends Animal{
    speak() {
        // 要把抽象类的方法执行了才不会报错
    }
}

继承vs多态

  • 继承 子类继承父类,子类除了拥有父类所有的特性外,还有一些更具体的特性
  • 多态 由继承而产生了相关不同的类,对同一个方法可以有不同的响应

接口

  • 用来描述一种对象解构或者对象的形状
  • 用来描述一种抽象的特性集合
interface UserInterface{
    name:string
    age:number
}
let user:UserInterface= {
    name:'zhufeng',
    age:10
}

// 抽象特性集合
interface Flyable{
    fly():void
}
class Bird implements Flyable{
    fly(){
        console.log('小鸟飞')
    }
}

interface Person6 {
    readonly id: number;
    name: string
    [propName:string]:any // [propName] key 表示未知的其它属性
}
let p3: Person = {
    id: 1,
    name: 'zhufeng'
}
// 接口也可以继承
interface speakable2{
    speak():void
}
interface speakChinese{
    speakChinese():void
}
class chinesePerson implements speakChinese {
    // 要同时实现接口及继承接口的方法
    speakChinese() {}
    speak(){}
}

// 函数类型接口
// 接口还可以用来约束函数
interface Discount {
    (price:number):number
}
function discount(price:number):number{
    reuturn price*.8
}
let d:Discount = discount(10)

// 可索引接口
// 可以对对象和数组进行约束

interface UserInterface1 {
    [index:number]:string
}
let user1:UserInterface1 = ['a', 'b', 'c'] // 索引是数字

interface UserInterface2 {
    [index:string]:string
}
let user2:UserInterface2 = {name: 'zhufeng'} // 

泛型

在定义函数、接口或类的时候,不预先指定具体的类型,而是在使用的时候再制定类型的一种特性

// T相当于占位符,在函数使用的时候才传进来
function createArray<T>(length:number,val:T):t[] {
    let arr:T[] = []
    for (let i = 0;l<length;i++) {
        arr[i] = val
    }
    return arr
}

createArray<string>(3,'x')

类数组

function sum(...args:number[]) {
    let a2:IArguments = arguments // arguments就是类数组
}
sum(1,2,3)
// IArguments 相当于一个接口
interface IArguments {
    [index: number]:any;
    length:number;
    callee: Function
}
let root = document.getElementById('root')
let children:HTMLCollection = root.children
let childNodes:NodeListOf<ChildNode> = root.childNodes

泛型类

在类中使用泛型

T = Type

 class MyArray<T>{
     list:T[] = []
     add(val:T) {
         this.list.push(val)
     }
     getFirst():T {
         return this.list[0]
     }
 }
let myArray = new MyArray<number>() // 使用时不写泛型也不会报错,会进行类型推论
myArray.add(1);myArray.add(2)
let f = myArray.getFirst() // 1

// 泛型接口 就是在定义接口的时候使用泛型
interface SUM<T> {
    (a:T,b:T):T
}
let sum3:SUM<number> = function(a:number, b:number):number{
    return a+b
}
let r2 = sum3(1,2)

// 泛型可以有多个
// tuple 长度和类型都确定的数组
function swap<A,B>(tuple:[A,B]):[B,A] {
    return [tuple[1], tuple[0]]
}
swap<string,number>(['a',1]) // [1,'a']

// 默认泛型类型 T=number 默认值
class MyArray<T=number>{
     list:T[] = []
     add(val:T) {
         this.list.push(val)
     }
     getFirst():T {
         return this.list[0]
     }
 }
let myArray = new MyArray<string>() // 使用时不写泛型也不会报错,会进行类型推论
myArray.add(1);myArray.add(2)
let f = myArray.getFirst() // 1

// 泛型的约束
// 在函数中使用泛型的时候,由于预先不知道泛型的类型,所以不能随意访问相应类型的属性和方法
function logger<T>(val:T) {
    console.log(val.length)// 这里不知道val的参数类型,这样写会报错
}
interface LengthWise{
    length: number
}
// T 要实现LengthWise这个接口,接口中定义了length的类型
function logger<T extends LengthWise>(val:T) {
    console.log(val.length)
}

// 泛型类型的别名
type Cart<T> = {list:T[]}|T[]
let cart:Cart<string> = ['a','b','c']
let cart2:Cart<string> = {list: ['a','b','c']}

// 泛型接口vs泛型类型别名
// 接口会创建一个新的名字,它可以在任意地方被调用。而类型别名并不是创建新的名字,例如报错信息就不会使用别名
// 类型别名不能被extends 和 implements,这时我们应该尽量使用接口代替类型别名
// 当我们需要使用联合类型或元组类型的时候,类型别名会更合适

解构类型系统

  • 接口的兼容性
    • 如果传入的变量和声明的类型不匹配,TS就会进行兼容性检查
interface Animal {
    name: string;
    age:number;
    gender:number
}
let a:Animal={
    name: 'zhufeng';
    age:10,
    gender:0
}
interface Person {
    name:string;
    age:number
}
function getName(p:Person):string {
    return p.name
}
getName(a)
// getName 的参数p:Person是person类型的接口,a是animal的接口,跟person接口相比,属性多了一个gender属性
// 在检查参数类型的时候,并不是比较接口类型,而是比较具体的属性是否兼容,对应的属性只能多,不能少

// 基本数据类型的兼容性
let num:string|number;
let str:string;
num = str

// str2 赋值给num2 是因为num2 有toString方法,是个字符串,字符串可以给字符串赋值
let num2:{
    toString():string
}
let str2:string
num2 = str2

// 类的兼容性
// 父子之间能不能赋值,跟是不是父类子类没有关系,关键就看要的属性有没有
class Perent{
    name:string
}
class child {
    age:number
}
let p:Parent = new Person()
let c:Child = new Child()
// 将一个子类的实例赋给父类的变量
let pp:Parent = new Child()
// 将一个父类的变量赋给一个子类的变量
let cc:Child = new Parent()

// 函数的兼容性
// 比较函数的时候,先比较函数上的参数,在比较函数上的返回值
// 参数是可以省略的
type SumFunc = (a:number,b:number)=>number
let sum:SumFunc;
sum = function(a:number,b:number):number{
    return a + b
}
sum2 = functon (a:number):number{
    return a
}
// 参数可以少不能多 
sum3 = functon ():number{
    return 0
}

// 这里可不是箭头函数,箭头左边是参数列表, 右边是返回值,是一个对象,声明的是属性而不是值
// 返回值可以多,不能少,不然调用属性的时候会报错
type GetPerson = () => {name: string,age:number}
let getPerson:GetPerson = function() {
    return {name: 'zhufeng',age:10}
}

// 函数参数的双向协变
// 函数的参数中目标兼容源,或者源兼容目标都可以,只有一个成立就可以
type LogFunc= (val:number|string)=>void
// LogFunc 兼容下面的 log1
let log1:LogFunc;
log1 = function(val:number) {console.log(val)}
// log2 兼容上面的LogFunc
log2 = function(val:number|string|boolean) {
    console.log(val)
}

// 泛型的兼容性
// 泛型在判断兼容性的时候,会先判断具体的类型,再进行兼容性的判断
interface Empty<T> {}
let x1:Empty<string>
let y1:Empty<number>
x1 = y1

interface NotEmpty<T> {data:T}
let x2:NotEmpty<string>={data: '123'}
let y2:NotEmpty<number>={data:123}
x2 = y2

// 枚举的兼容性
// 枚举和数字兼容  比较值
enum Colors {
    Red, // 0
    Yellow, // 1
    Blue // 2
}
// 相当于
// let Colors ={ '1': Red,'2': Yellow; '3': Blue}

let num:number = Colors.Red // 0

let c:Colors;
c = Colors.Red
c = 1
// 数字可以赋值给枚举变量,枚举变量也可以赋值给数字 

类型保护

类型保护就是一些表达式,他们在编译的时候就能通过类型信息确保某个作用域内变量的类型

类型保护就是能通过关键字判断出分支中的类型

// 分支中判断类型
function double(input: string|number|boolean) {
    if (typeof input === 'number') {
        return input*2
    }
    if (typeof input === 'string') {
        return input+input
    }
    if (typeof input === 'string') {
        return !input
    }
}

class Bird{
    name1: string
}
class Dog {
    name2: string
}
function getName(animal:Bird|Dog) {
    if (animal instanceof Bird) {
        return animal.name1
    }
    if (animal instanceof Dog) {
        return animal.name2
    }
}

// null保护
// 在默认情况下 null的检查是不严格的
function getFirstLetter (str: string|null) {
    // 第一种处理方式
    str = str || ''
    return str.charAt(0)
}

// 链判断运算符 ES2020
// 是一种先检查属性是否存在你,再尝试访问改属性的运算符,符号位?
// 原理就是三元运算符
let a:any={
    b:'zhufeng'
}
a = null
console.log(a?.b) // 'zhufeng'
console.log(a == null?undefined:a.b)

// 可辨识的联合类型
// 就是利用联合类型中的共有字段进行类型保护的一种技巧
// 相同字段的不同取值就是可辨识
// 在联合属性中,通过相同的值来判断 class
interface WarningButton {
    class:'warning',
    text1: '修改'
}
interface DanagerButton {
    class:'danager',
    text2: '删除'
}
type Button = WarningButton | DangerButton
function getButton(button:Button) {
    if (button.class == 'warning') {
        console.log(button.text1)
    }
    if (button.class == 'danger') {
        console.log(button.text2 )
    }
}

interface Bird {
    swing:number
}
interface Dog {
    leg: number
}
// 判断属性有没有
function getNumber(animal:Bird|Dog) {
    if ('swing' in animal) {
        console.log(animal.swing)
    }
    if ('leg' in animal) {
        console.log(animal.leg)
    }
}

// 以dog bird为例-----------------------------

// 自定义类型检查函数 x is Bird类型谓词
function isBird (x:Bird|Dog):x is Bird {
    return (x as Bird).swing>0
    return (<Bird>x).swing>0 // 使用断言,只能用Bird或者Dog
}
// 如果是鸟的话,返回鸟的翅膀的个数,如果是狗的话,返回狗的腿的个数
function getAnimal (x:Bird|Dog) {
    if(isBird(x)) {
        console.log(x.swing)
    } else {
        console.log(x.leg)
    }
}

类型变换

// 交叉类型
// 将多个类型合转成一个类型
interface Bird {
    name:string,
    fly():void
}
interface Person {
    name:string;
    eat():void
}
// 取的是接口中属性的并集
type BirdMan = Bird & Person
// 里面的属性一个都不能少&, |可以少
let bm:BirdMan = {
    name:'zhufeng',
    fly(){}
    eat(){}
}
// 兼容性检查,仅在传参的时候可以去那样判断,属性可以多,但赋值的时候不行
type People = {
    name:string,
    age:number
}
let p:People = {
    name: 'zhufeng',
    age: 10,
    gender: 'male'  // 属性不能多
}
// ----------------
let p = {
    name:'zhufeng',
    age: 10
}
// 用一个对象来定义一个类型,再用类型类限制变量p
type People = typeof p
let p:People ={
    name: 'zhufeng',
    age:10
}

// 索引访问操作符
interface Person{
    name:string;
    age:number
    job: {
        name:string
    },
     hobbies:{name:string, level:number}[]
}
let job:Person['job'] = {name: '前端'}
let hobbyLevel:Person['hobbies'][0]['level'] = 10

// keyof
// 索引类型查询操作符
interface Person {
    name:string;
    age:number;
    gender: 'male'|'female'
}
function getValueByKey(p:Person,key:string) {
    return p[key]
}
// 接口中的key
getValueByKey(p:Person,key:keyof Person) {
    return p[key]
}
let p:Person = {
   name: 'zhufeng',age:10,gender:'male' 
}
let r = getValueByKey(p,'name') // zhufeng

// 映射类型
// 在定义的会后用in操作符去批量定义类型中的属性
interface Person {
    name:string;
    age:number;
    gender?: 'male'|'female'
}
// ? 属性可选的意思
type PartPerson = {
    [key in keyof Person]?:Person[key]
    // 相当于每个属性后面加个?
}
let p:Person = {
    name:'zhufeng',
    age:10,
    gender:
}
let p:PartPerson={
    // 参数少传也不会报错
}

// partial 把属性变成可选
let p: Partial<Person> = {
    
}
// required 将传入的属性变成必选项,用-? 表示
// Reaonly 通过为传入的属性每一项都加上readonly修饰符来实现
// pick 能够从传入的属性中摘取某一项返回
Pick<Animal,'name'> // 从animal中去name属性
    
// 条件类型
// 在定义泛型的时候能够添加逻辑分支,以后泛型更加灵活
interface Fish {
    name1:string
}
interface Water {
    name2:string
}
interface Bird {
    name3:string
}
interface Sky {
    name4:string
}
type Conditon<T> = T extends Fish?Water:Sky
let con:Condition<Fish> = {name2: 'water'}
// 相当于 let con:Water = {name: 'water'}






相关文章

  • JAVA 之路第一讲

    数据类型: 基础数据类型 包装器数据类型 引用数据类型 null 数据类型 基础数据类型: 整型 byte(字节型...

  • php 数据类型和数据类型转化

    一、数据类型 基础数据类型 复合数据类型 特殊数据类型 二、获取数据类型 三、打印数据类型和值 四、数据类型判断 ...

  • OC和C中的数据类型

    数据类型对比 C语言数据类型C语言数据类型 OC数据类型

  • JAVA 核心笔记 || [2] 数据类型

    JAVA数据类型分为两大数据类型: 1.内置数据类型2.引用数据类型 内置数据类型 引用数据类型 上篇 : 开篇 ...

  • 数据类型

    数据类型作用:数据类型不同,空间大小不同。 数据类型分类:基本数据类型、引用数据类型基本数据类型:整数型、浮点型、...

  • Java知识之数据类型

    Java数据类型图表## Java数据类型分为:### 基础数据类型 引用数据类型 null类型 基础数据类型分別...

  • JAVA基础第四天

    JAVA数据类型---布尔类型; 数据类型转换自动数据类型转换 强制数据类型转换

  • Java数据类型(慢慢积累,对于事物的理解也会不一样)

    Java的数据类型: 1. 内置数据类型(基本数据类型); 2. 引用数据类型; Java基本数据类型:(...

  • 【IOS 开发】 数据类型详解

    1. 数据类型简介及输出 (1) 数据类型简介 数据类型简介: Object - C 数据类型 分为 基本数据类型...

  • iOS 数据类型简介及输出

    一、数据类型简介及输出 1.数据类型简介 数据类型简介 : Object - C 数据类型 分为 基本数据类型, ...

网友评论

      本文标题:数据类型

      本文链接:https://www.haomeiwen.com/subject/kalndhtx.html