Ts 的学习 安装ts
初始化ts
下载一个包?
类型
顶级类型 any unknown object
Number String Boolean
number string boolean
对象是大写 实现是小写
unknown 只能赋给自身,或者是any
object Object object 只能用引用类型?不支持原始类型
{}类型无法做修改
interface 自定义类型
interface Z 后面跟着打要大写
interface Z{
name : string
age:number
}
可以在字段前面加一个 readonly 只可以读
接口可以继承接口
extend 关键字
基本类型都差不多 讲一下 不常见的
交叉类型
类型断言
1 2 3 4 let fn = function(num:number | string):void{ console.log((num as string).length) } fn(12345)
断言 把某些东西转换成某些类型。
内置对象 Number Date RegExp 等等。
dom对象 bom
类 class 关键字
抽象类
抽象类 只能描述,不能定义
抽象类可以被其他类实现
元组 枚举 enum
never 类型 symbol类型 类型注解 作用:相当于强类型语言中的类型声明
语法:(变量/函数):type
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 let bool :boolean =true let num :number = 123 let str : string = 'abc' let arr1 : number [] = [1 ,2 ,3 ]let arr2 : Array <number > =[1 ,2 ,3 ]let arr2 : Array <number | string > = [1 ,2 ,3 ,'4' ]let tuple : [number ,string ] = [0 ,'1' ] add = (x :number ,y :number ):number => x + y let obj : {x : number ,y :number } = {x :1 ,y :2 }obj.x = 3 let s1 : symbol = Symbol ()let s2 = Symbol ()let un : undefine = underfinedlet nu : null = null let noReturn = ( ) => {}let xlet error = ( ) =>{ throw new Error ('error' ) } let endless = ( ) =>{ while (true ){} }
有关枚举类型
枚举:一组有名字的常量集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 enum Role { Reporter , Developer , Maintainer , Owner , Guest } console .log (Role )enum Message { Success = '恭喜' , Fail = '抱歉' } enum Answer { N, Y = 'Yes' } Role .Reporter = 2 enum Char { a, b = Char .a , c = 1 + 3 , d = Math .random (), e = '123' .Length } const enum Month { Jan , Feb , Mar } let month = [Month .Jan ,Month .Feb ,Month .Mar ]enum E {a,b}enum F {a=0 ,b=1 }enum G {a = 'apple' ,b = 'banana' }let e : E = 3 let f : F = 3
接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 interface List { id : number ; name : string ; [x :string ];any } interfave Result { data List [] } function render (result: Result ){ result.data .forEach ((value ) => { console .log (value.id ,value.name ) }) } let result = { data :[ {id :1 ,name :'A' } {id :2 ,name :'B' } ] } render (result)[x :string ]:string
另外问了下newbing 关于索引签名的事情
涉及到TypeScript中的索引签名(index signature)的用法和规则。索引签名是一种用来描述对象的结构的类型注解,它指定了对象的键和值的类型。索引签名有两种形式,一种是字符串索引签名,另一种是数字索引签名。字符串索引签名的形式是[key: string]: ValueType,表示对象的键是字符串类型,值是ValueType类型。数字索引签名的形式是[key: number]: ValueType,表示对象的键是数字类型,值是ValueType类型。
在你的例子中,你定义了一个接口MyObject,它有两个索引签名,一个是字符串索引签名,一个是数字索引签名。这样的接口是合法的,但是有一些限制和约束。首先,数字索引签名的值类型必须是字符串索引签名的值类型的子类型或相同类型。这是因为JavaScript会将数字类型的键转换为字符串类型的键,所以数字索引签名实际上是字符串索引签名的一种特殊情况。如果数字索引签名的值类型和字符串索引签名的值类型不一致,那么就会出现类型不兼容的错误。例如,你的第一个例子中,数字索引签名的值类型是number,而字符串索引签名的值类型是string,这就不满足子类型或相同类型的要求,所以会报错。你的第二个例子中,数字索引签名的值类型和字符串索引签名的值类型都是string,这就满足了要求,所以不会报错。
其次,如果一个接口有两个索引签名,那么它不能有其他的属性。这是因为索引签名表示对象的结构是不确定的,它可以有任意数量和类型的键,所以不能再添加其他的确定的属性。如果一个接口有其他的属性,那么它只能有一个索引签名,而且这个索引签名的值类型必须包含或相同于其他属性的值类型。例如,下面的接口是合法的,因为它只有一个索引签名,而且这个索引签名的值类型是string | number,它包含了其他属性的值类型:
interface MyObject { [key: string]: string | number; name: string; age: number; }
大致是这样子的 必须包括 或者相等 下面是newbing 生成的一首诗。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 type Poem = { title : string ; author : string ; content : string []; }; let TypeScript : Poem = { title : "TypeScript" , author : "Bing" , content : [ "TypeScript is a superset of JavaScript," , "It adds types and interfaces to the script," , "It helps you write code that is clear and robust," , "It catches errors and bugs before they erupt." , "" , "TypeScript is a language that compiles to JavaScript," , "It runs on any browser or platform that supports it," , "It offers features like classes, generics and modules," , "It makes your code more readable, reusable and scalable." , "" , "TypeScript is a poem that expresses my admiration," , "It is a tribute to the developers who created this innovation," , "It is a challenge to the programmers who want to learn this creation," , "It is a invitation to the readers who want to enjoy this narration." ] }; console .log (TypeScript .title + " by " + TypeScript .author );console .log (TypeScript .content .join ("\n" ));
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 interface Lib { ():void ; verision :string ; doSomething ():void ; } function getLib ( ){ let lib :Lib = (() => {}) as Lib ; lib.version = '1.0' ; lib.doSomething = () => {} return lib; }
函数 4种定义函数
1 2 3 4 5 6 7 8 9 10 function add1 (x:number ,y:number ){ return x + y } let add2 :(x:number ,y:number ) => number type add3 = (x:mumber,y:number ) => number interface add4{ (x :number ,y :number ):number }
后面三种 只是定义并没有实现。
函数可以加可选参数,但是可选参数必须在必选参数后面。或者可以给参数提供一个默认值。
1 function add6(x:number,y=0,z:number,q=1)
如果默认参数 在需要传参的前面,那么必须传入一个underfine,否则会报错。如果在后面则无所谓。
函数重载 同一个函数名字,但是对应参数不一样。或者是返回值
1 2 3 4 5 6 7 8 9 10 11 function add8(...rest:number[]):number; function add8(...rest:string[]:string;) function add8(...rest:any[]): any{ leet firstt = rest[0] if (typeof first === 'string'){ return rest.join('') } if(typeof first === 'number'){ return rest.reduce((pre,cur) => pre + cur ) } }
类 类的实现 1 2 3 4 5 6 7 8 9 10 class Dog { constructor (name:string ){ this .name = name } name : string run ( ){} } console .log (Dog .prototype )let dog = new Dog ("wangcai" )console .log (dog)
类的继承 1 2 3 4 5 6 7 class Husky extends Dog { constructor (name :string ,color :string ){ super (name) this .color = color; } color :string }
类的属性 有三种 public private protect
记得以前学java 阿伟讲的很清楚。
public 谁都能进
private 只有类成员 才能进
protect 就是名义上是这个家的成员也能进 受法律保护。外面的孩子。只能在类或者子类中使用,不能在实例中使用
抽象类和多态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 abstract class Animal { eat ( ){ console .log ('eat' ) } abstract sleep ():void } class Dog extends Animal { constructoi (name:string ){ super () this .name = name } name : string run ( ) {} sleep ( ){ console .log ('dog is sleeping' ) } } let dog = new Dog ('wangcai' )dog.sleep (); Class Cat extends Animal { sleep ( ){ console .log ('Cat is sleeping' s) } } let cat = new Cat ();let animals : Animal [] = [dog,cat]animals.forEach (i => { i.sleep () }) class WorkFlow { step1 ( ){ return this ; } step2 ( ){ return this ; } } new WorkFlow ().step1 ().step2 ()class Myglow extends WorkFlow { next ( ){ return this ; } } new Myflow ().next ().stpe1 ().next ().step2 ()
类和接口之间的关系 类可以实现接口
接口之间可以互相继承
接口继承类 such as
1 2 3 4 5 6 7 8 9 10 11 12 13 class Auto { state = 1 } interface AutoInterface extends Auto { } class C inplements AutoInterface { state = 1 } class Bus extends Auto inplements AutoInterface { }
泛型 不预先确定的数据类型,具体的类型在使用的时候 才能确定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function log<T>(value :T):T{ console .log (value); return value; } log<string []>(['a' ,'b' ]) log (['a' ,'b' ])type Log = <T>(value:T ) => T<T> 表示这个函数类型是一个泛型函数类型,其中 T 是一个类型参数 interface Log <T>{ {value : T}:T } let myLog : Log <number > = logmyLog (1 )interface Log <T = string >{ (value :T):T }
泛型类与泛型约束 1 2 3 4 5 6 7 8 9 interface Length { length : number } function log<T extend Length >(value :T):T{ console .log (value,value.length ) return value } log ([1 ])log ('123' )
类型检查机制 类型推断 不需要指定变量的类型(函数的返回值类型),typescript可以根据某些规则自动地为其推断出一个类型
类型断言可以自己指定属性,不需要他来推断
1 2 3 4 5 6 7 8 9 10 interface Foo { bar : number } let foo = {} as Foo for .bar = 1 let foo : Foo = { bar : 1 }
类型兼容性 当一个类型Y 可以被赋值给另一个类型X时,我们就可以说类型X兼容类型Y
X兼容Y: X(目标类型) = Y(源类型)
关闭tsconfig.json 中的‘strictNullChecks’
string s 可以被赋值给null
字符型可以兼容null类型。
源类型如果包括一个类型的所有类型,成员少的可以兼容成员多的。
对象类型 和 接口类型不一样?
对象: 成员对象多的可以兼容成员少的 跟接口 相反。
? 没懂
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 interface Point3D { x :number ; y :number ; z :number ; } interface Point2D { x :number ; y :number ; } let p3d = (point:Point3D ) => {};let p2d = (point:Point2D ) => {}; 为什么 Point2D = point3D 而 p2d = p3d 则不行
对于接口,TypeScript 使用的是结构性类型系统。在这种类型系统中,如果 TypeA
是 TypeB
的子类型,那么 TypeA
的对象可以赋值给 TypeB
的对象。在你的例子中,Point3D
接口包含了 Point2D
接口的所有属性,因此 Point3D
可以看作是 Point2D
的子类型,所以 Point3D
类型的对象可以赋值给 Point2D
类型的对象²。
然而,对于函数,TypeScript 使用的是名义类型系统。在这种类型系统中,函数的参数类型必须完全匹配。也就是说,如果一个函数的参数类型是 TypeA
,那么我们只能将类型为 TypeA
的对象传递给这个函数,不能将 TypeA
的子类型的对象传递给这个函数¹。在你的例子中,函数 p3d
和 p2d
的参数类型分别是 Point3D
和 Point2D
,尽管 Point3D
是 Point2D
的子类型,但你不能将 p3d
赋值给 p2d
,因为 p3d
接受的参数类型是 Point3D
,而 p2d
接受的参数类型是 Point2D
,这两者并不完全匹配¹。 */
在 TypeScript 中,你可以将 p2d
赋值给 p3d
,因为 p2d
函数接受的参数类型 Point2D
是 p3d
函数参数类型 Point3D
的超类型。换句话说,任何 Point2D
类型的对象都是 Point3D
类型的对象,因此 p2d
函数可以接受任何 p3d
函数可以接受的参数。
这是因为在 TypeScript 的类型系统中,函数的兼容性是基于参数列表和返回类型的。对于参数列表,TypeScript 采用 “鸭子类型”(Duck Typing)或 “结构子类型化”(Structural Subtyping)。在这种类型系统中,如果 TypeB
的每个属性都存在于 TypeA
中,那么 TypeB
就被认为是 TypeA
的子类型。因此,如果一个函数 f1
的每个参数都存在于另一个函数 f2
的参数列表中,那么 f1
就可以被赋值给 f2
。
所以,你可以将 p2d
赋值给 p3d
,但不能将 p3d
赋值给 p2d
,因为 p3d
的参数类型 Point3D
包含了 p2d
的参数类型 Point2D
中没有的属性 z
。
有待商榷 上面 后面在寻找资料。
枚举兼容性 enum Fruit{Apple,Banana}
enum Color{Red,Yellow}
let fruit:Fruit.Apple = 3
let no: number = Fruit.Apple
let color: Color.Red = Fruit.App 这是不行的
// 类的兼容性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 class A { constructor (p:number ,q:number ){} id : numner = 1 private name : string ='' } class B { static s = 1 constructor (p:number ){} id :number = 2 private name : string = '' } /因为 都具有一个实例属性id 构造函数和静态成员是不做比较的。*/ 有私有成员 父类和子类是互相兼容的
泛型兼容 只有在泛型给成员变量使用时才会影响兼容性
类型保护 交叉类型和联合类型
未完待续