typescript 语法总结
<p><strong>typescript中的数据类型</strong><br>1.基础类型 string,number,null,undefined,boolean</p><p>undefined:一个没被分配值的变量</p>
<p>null:人为分配一个空值</p>
<p><strong><span style="color: rgba(255, 0, 0, 1)">strictNullChecks</span></strong>: tsconfig.json中配置项,值为on时,在使用可能是null的值前,需要显示的检查</p>
<p>2.数组类型Array<T>,T代表数组中的元素类型(本写法要求元素类型统一)</p>
<p>3.any,unknown,noImplictAny</p>
<p>unknown:是any的替代品,将unknown类型变量赋值给其它类型变量时,会报错。</p>
<p><span style="color: rgba(255, 0, 0, 1)"><strong>noImplictAny</strong></span>:(implict:隐式 inplict:显式):项目中是否允许隐式any,tsconfig.json中配置项</p>
<p> </p>
<p><strong>类型标注</strong> let len:Number = 11; //也可写成let len = 11,ts将进行类型推导 <em> 窄化??</em></p>
<p><strong>函数</strong>:规定输入输出值类型</p>
<p>function greet(name:string):number{</p>
<p> console.log(name)</p>
<p>}</p>
<p>匿名函数 contexture typing:根据上下文猜测匿名函数参数的类型</p>
<p>const arr = ['frist','second','third'];</p>
<p>arr.forEach(function(s){ //匿名函数中当前项s,通过上下文推导出为string类型,所以支持toUpperCase方法</p>
<p> console.log(s.toUpperCase())</p>
<p>})</p>
<p><strong>联合类型:</strong>ts会针对联合类型做排除法,联合类型只能使用两个类型公共的方法。</p>
<p>function greet(name:string<span style="color: rgba(255, 0, 0, 1)"><strong> |</strong> </span>number):number{</p>
<p> // 只能使用传入类型公共的方法</p>
<p> if(typeof name === 'string'){ console.log(id); return;}</p>
<p> console.log(name.toUpperCase());</p>
<p> }</p>
<p><strong>类型别名type:支持多种类型组合(&),可以简单理解为字符串的替换<br></strong>type id=number | string;</p>
<p>type Point = {x:name;y:number;}</p>
<p>type Bear = Point <strong>&</strong> {honey:boolean} //多种类型组合(&)</p>
<p>let uid :id = 100 //<strong>可以简单理解为字符串的替换, </strong>typeof uid 会返回number而不是id</p>
<div>type更多用法:</div>
<div><code class="js plain">type StringOrNumber = string | number; </code>
<div class="line number2 index1 alt1"><code class="js plain">type Text = string | { text: string }; </code></div>
<div class="line number3 index2 alt2"><code class="js plain">type NameLookup = Dictionary<string, Person>; </code></div>
</div>
<div><code class="js plain">type Callback<T> = (data: T) => void; // 对T进行Callback操作</code>
<div class="line number5 index4 alt2"><code class="js plain">type Pair<T> = ;</code></div>
<div class="line number6 index5 alt1"><code class="js plain">type Coordinates = Pair<number>;</code></div>
<div class="line number7 index6 alt2"><code class="js plain">type Tree<T> = T | { left: Tree<T>, right: Tree<T> };</code></div>
</div>
<div> </div>
<p><strong>接口interface:支持继承extends,接口被定义两次时定义的属性会合并(但相同属性不能更改类型,高阶能力)</strong></p>
<p>interface Point{ x:name;y:number; }</p>
<p>interface Bear <strong>extends</strong> Point{ honey:boolean } //继承</p>
<div>类型别名和接口,都可以按以下方式调用:<br>
<div>const bear1:Bear = {</div>
<div> x:12,</div>
<div> y:'lele'</div>
<div>}</div>
<div>console.log(bear1)</div>
<div> </div>
<div> 更多知识见 《typescript中的interface和type到底有什么区别详解》https://www.jb51.net/article/163299.htm</div>
<div> </div>
</div>
<p><strong>类型断言assertion,只是提示作用</strong></p>
<p>const x = 'hello'<strong> as number // 可使用 const x = </strong>('hello' <strong>as</strong> unknown) <strong>as</strong> string 来欺骗ts</p>
<p><strong>html元素对应的接口名称 https://www.cnblogs.com/liuxu-xrl/p/15401274.html</strong></p>
<p> </p>
<p><strong>字面类型:常量const的值为字面值,不能修改。相对于let 。</strong></p>
<p><strong>可以用字面类型约束一些特殊的函数:</strong></p>
<div>
<div>interface options {</div>
<div> id:number</div>
<div>}</div>
<div>// 字面类型</div>
<div>function configure(x:options | <strong>'auto'</strong>){</div>
<div> console.log(x)</div>
<div>}</div>
<div>configure('auto');</div>
<div>configure({id:1});</div>
<div>configure(''); //类型“""”的参数不能赋给类型“options | "auto"”的参数。</div>
<div> </div>
<div>字面类型的坑点:只能处理当前一级传值</div>
<div><hr>
<div>function handleReq(url:string,method:<strong>"GET"|"POST"</strong>){</div>
<div> console.log(url,method)</div>
<div>}</div>
<div>const req = { url:'http://abd.com',method:"GET" };</div>
<div><span style="color: rgba(255, 0, 255, 1)">// handleReq(req.url, req.method); // 报错类型“string”的参数不能赋给类型“"GET" | "POST"”的参数。</span></div>
<div><span style="color: rgba(0, 0, 0, 1)"><strong>正确写法0:</strong></span></div>
<div>
<div><strong>handleReq(req.url,"GET")</strong></div>
</div>
<div>正确方法1:</div>
<div>handleReq(req.url,<span style="color: rgba(255, 0, 0, 1)">req.method as "GET"</span>)</div>
正确方法2:<br>
<div>const req2 = { url:'http://abd.com',<span style="color: rgba(255, 0, 0, 1)">method:"GET" as "GET"</span>};</div>
<div>
<div>handleReq(req.url,req.method)</div>
<div>正确方法3:</div>
<div>const req2 = { url:'http://abd.com',method:"GET"}<span style="color: rgba(255, 0, 0, 1)"> as const</span>;</div>
</div>
<div>handleReq(req2.url,req2.method)</div>
<div> </div>
<div><strong>js对象逃避类型检查方式</strong></div>
<div>
<div>strictNullChecks:true时,需要显式的检查可能是null的值<br>
<div>function doSomeThing(x:string | null){</div>
<div> console.log("hello,"+x.toUpperCase()); <span style="color: rgba(255, 0, 255, 1)">//报错: 对象可能为 "null"。</span></div>
<div> console.log("hello,"+x<span style="font-size: 18pt"><strong>!.</strong></span>toUpperCase()); // 可以用!操作符,来断言某个值不是空值</div>
<div>}</div>
<div> </div>
<div><strong>枚举类型 enum:</strong>枚举类型默认会返回数字,支持反向取属性(也可以赋值为字符串,但是没必要,因为可以反向获取;也可以混合不同的数据类型,但是会增加复杂度)</div>
<div>
<div>
<div>enum Direction {</div>
<div> up=1,</div>
<div> down,</div>
<div> left,</div>
<div> right</div>
<div>}</div>
<div>console.log(Direction.down,Direction.left) //2 3 返回数字</div>
<div>console.log(Direction) //left 反向操作提取Enumerate中的字符串(属性名称),也叫Reverse Mapping</div>
<div>function f(obj:{up:number}){</div>
<div> return obj.up</div>
<div>}</div>
<div>f(E)</div>
<div>f({up:1,down:2}) // Error 类型“{ up: number; down: number; }”的参数不能赋给类型“{ up: number; }”的参数。对象文字可以只指定已知属性,并且“down”不在类型“{ up: number; }”中。</div>
<div> </div>
<div><strong>泛型</strong>:一种抽象一类事物的共性特征的编程手段,它允许将类型作为其它类型的参数(表现形式),从而分离不同关注点的实现(作用)。泛型可以根据传入的函数的参数,自动推导出泛型类型和函数返回值类型。</div>
<div><strong>关注点(interest Point)</strong>不同:程序里有三种表达:<br>接口interface:一种方面的<strong>描述</strong>,一个类型可以拥有多个方面的特性</div>
<div>继承inheritance:一种强表达。松树->extends->树</div>
<div>泛型Generics:是对共性的<strong>提取</strong>。e.g 在造床这件事务上,桃木,红木等等木头都有这个作用</div>
<div>e.g</div>
<div> </div>
<div>
<div>
<div>// 以下方式,只能处理number类型</div>
<div>function identity1(arg:number):number{</div>
<div> return arg;</div>
<div>}</div>
<br>
<div><strong>// 泛型函数</strong></div>
<div>// 通过<strong>钻石操作符<></strong>,传入泛型的参数,结合函数的参数(类型)和函数的返回值类型,帮我们支持所有类型</div>
<div>function identity2<Type>(arg:Type):Type{</div>
<div> return arg</div>
<div>}</div>
<div>let out2 = identity2<string>('MyString'); //等价于 let out = identity2('MyString'); 此时,可以通过值推导出传入值类型</div>
<div>// out2 = 100; //不能将类型“number”分配给类型“string”。</div>
</div>
<div><br>
<div><strong>// 泛型类</strong></div>
<div>class GenericNumber<T>{</div>
<div> private zeroValue:T;</div>
<div> constructor(v:T){</div>
<div> this.zeroValue = v;</div>
<div> }</div>
<div> public add(x:T,y:T){</div>
<div> return this.zeroValue + '' + x + y; //运算符“+”不能应用于类型“T”和“T”。=> 因为仅数字能进行运算</div>
<div> }</div>
<div>}</div>
<div>let gener = new GenericNumber<string>('hello,');</div>
<div>console.log(gener.add('Lucy','Lily')); //hello,LucyLily</div>
<div><br>
<div><strong>// extends interface 给泛型添加约束</strong></div>
<div>interface Lengthwise{</div>
<div> length:number</div>
<div>}</div>
<div>function loggingIdentity<Type<strong> extends Lengthwise</strong>>(arg: Type):Type{ // 让Type继承<strong>Lengthwise</strong>以支持.length</div>
<div> console.log(arg.length); // <Type<strong> extends Lengthwise</strong>>改成<Type>时,因不确定Type类型,所以找不到.length属性,导致报错</div>
<div> return arg</div>
<div>}</div>
<div>loggingIdentity<string>('test') // 也可简写为 loggingIdentity('test') ,通过传入值自动推导Type<br>
<div><br>
<div><strong>// type keyof 给泛型添加约束 </strong></div>
<div>type Point = {x:number;y:number}</div>
<div>type P = keyof Point; //P = 'x' | 'y',即Point中所有的参数(属性)</div>
<br>
<div>function getProperty<Type,Key<strong> extends keyof</strong> Type>(obj:Type,key:Key){</div>
<div> console.log(obj)</div>
<div> return obj</div>
<div>}</div>
<div>let x1 = {a:1,b:2,c:3,d:4}; //因为是静态的,所以可以用keyof操作符获取所有的key,若对象x1的类型为any,那么keyof就没有意义了</div>
<div>// x1.z= 10; // 类型“{ a: number; b: number; c: number; d: number; }”上不存在属性“z”。</div>
<div>getProperty(x1,"d")</div>
<div>// getProperty(x1,"m") //类型“"m"”的参数不能赋给类型“"d" | "a" | "b" | "c"”的参数。</div>
</div>
</div>
<div><strong>实例化泛型类型,将类作为参数传入</strong></div>
<div>function create<Type>(c:{new ():Type}):Type{ // 也可写为function create<Type>(c:new ()=>Type):Type{</div>
<div> return new c();</div>
<div>}</div>
<div>create(Foo) //返回Foo的实力</div>
<div>e.g 实战实例</div>
<div>
<div>class BeeKeeper {</div>
<div> hasMask : boolean = true;</div>
<div>}</div>
<div>class ZooKeeper {</div>
<div> nametags: string = 'Mikle';</div>
<div>}</div>
<div>class Animal {</div>
<div> numLegs : number = 4;</div>
<div>}</div>
<div>class Bee extends Animal{</div>
<div> keeper:BeeKeeper = new BeeKeeper();</div>
<div>}</div>
<div>class Lion extends Animal{</div>
<div> keeper:ZooKeeper = new ZooKeeper();</div>
<div>}</div>
<div>function createInstance<A extends Animal>(c: new()=>A):A{</div>
<div> return new c();</div>
<div>}</div>
<div>console.log( createInstance(Lion).keeper.nametags ); //返回一个</div>
<div>console.log( createInstance(Bee).keeper.hasMask );</div>
<div> </div>
<div><span style="color: rgba(255, 0, 0, 1)"><strong>窄化(Type Narrowing)</strong>:<strong>本质是重新定义类型,解决联合类型校验的问题</strong></span></div>
<div> <strong>if + typeof:</strong></div>
<div><strong>typeof返回值类型:</strong>string","number","bigint","boolean","symbol","undefined","object","function"。注意typeof null==='object'</div>
<div><strong>真值窄化</strong>:帮我们更好的应对null,undefined,0等情况的判断</div>
<div><strong>JavaScript真值表</strong>(if时会进else的):0,null,undefined,NaN," "(the empty string),0n(the bigint version of zero)</div>
<div><strong>相等性窄化:隐式的窄化方法,相等性窄化。===,!==,== ,and != 都可以用来窄化类型。</strong></div>
<div>
<div>interface Container{</div>
<div> value:number | null | undefined;</div>
<div>}</div>
<div>function mulValue(container:Container,factory:number){</div>
<div> if(container.value<strong> !=null</strong>){ //此处!=可以过滤掉null,undefined两种类型(!=两侧的 undefined和null都会转成false )。如果替换为!==,会报错 ,因为到时<span class="mtk9">Container<span class="mtk1">.<span class="mtk9">value<span class="mtk1">为 <span class="mtk9">number<span class="mtk1">或<span class="mtk5">undefined</span></span></span></span></span></span></span></div>
<div> container.value *= factory;</div>
<div> return container.value</div>
<div> }</div>
<div> return container.value;</div>
<div>}</div>
<div>//number类型</div>
<div>let data = mulValue({value:10},2);</div>
<div>console.log(data)</div>
<div>//null或undefined类型</div>
<div>let data2 = mulValue({value:undefined},2);</div>
<div>console.log(data2)</div>
<div> </div>
<div><strong>in操作符窄化(type定义时)</strong></div>
<div>
<div><strong>type</strong> Fish = { swim:()=>void };</div>
<div><strong>type</strong> Bird = { fly:()=>void };</div>
<div>function move(animal:Fish | Bird){</div>
<div> if('swim' <strong>in</strong> animal) return animal.swim();</div>
<div> else animal.fly()</div>
<div>}</div>
<div>class myFish{</div>
<div> public swim(){</div>
<div> return 'swim'</div>
<div> }</div>
<div>}</div>
<div>console.log(move(new myFish()));</div>
</div>
<div>
<div><br>
<div>// <strong>instanceof 做窄化</strong>,</div>
<div>// 此处Date必须是真实存在的Function类型,不能是type</div>
<div>function move1(time: <strong>Date</strong> | string){</div>
<div> if(<strong>time instanceof Date</strong>){</div>
<div> console.log('time',time)</div>
<div> return 'time'</div>
<div> }</div>
<div>}</div>
<div>move1(new Date());</div>
</div>
</div>
<div> </div>
<div>组合类型推导</div>
<div>let x = Math.random() < 0.5 ? 10: "hello world!"; // <strong>系统会自动推导出x为number或string类型</strong></div>
<div>
<div>// xx = new Date() //Error <span style="color: rgba(255, 0, 255, 1)">不能将类型“Date”分配给类型“string | number”。 因为<span style="color: rgba(255, 0, 0, 1)">ts推导出 只能赋值为<strong>number或string类型</strong></span></span></div>
<div> </div>
<div> </div>
<div><span style="color: rgba(0, 0, 0, 1)"><strong>控制流分析:</strong></span></div>
<div><span style="color: rgba(255, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><strong>ts是如何做窄化的?</strong><span style="color: rgba(0, 0, 0, 1)">在语法分析阶段,ts编译器识别出类型卫兵表达式(e.g if(typeof padding === 'number' ) 、instanceof).然后对返回值逻辑分别做窄化,窄化的本质是重新定义类型。</span></span></span></div>
<div>
<div>
<div>// 控制流窄化</div>
<div>function exp1(){</div>
<div> let x :string | number | <strong>boolean</strong>;</div>
<div> x = Math.random()>0.5; // boolean</div>
<div> if(Math.random()<0.5){</div>
<div> x='hello'; // string</div>
<div> console.log(2,typeof x);</div>
<div> }</div>
<div> else{</div>
<div> x = 100; // number</div>
<div> console.log(3,typeof x);</div>
<div> }</div>
<div> return x; <strong> //string | number,<span style="color: rgba(255, 0, 0, 1)">没有Boolean了,因为上面的if,else语句已经把Boolean的可能干掉了</span></strong></div>
<div><span style="color: rgba(255, 0, 0, 1)">}</span></div>
<div>exp1();</div>
</div>
</div>
<div><span style="color: rgba(255, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)"> </span></span></span></div>
<div> </div>
<div><span style="color: rgba(255, 0, 255, 1)"><span style="color: rgba(255, 0, 0, 1)"><span style="color: rgba(0, 0, 0, 1)">断言操作符:</span></span></span></div>
<div>Assertion操作符as:提示ts某种类型是什么,当用户比ts更了解类型时使用,as影响的是当前函数内部</div>
<div>predicate操作符is:用户自定义的类型守卫,用于帮助Typescript Narrowing ,is影响的是当前函数的调用逻辑,函数内无效</div>
<div>
<div>function isFish(pet:Fish | Bird) :<span style="color: rgba(255, 0, 0, 1)"><strong> pet is Fish</strong> </span>{</div>
<div> // return pet.swim !== undefined // Error 类型“Bird”上不存在属性“swim”,因为pet is Fish</div>
<div> return (<span style="color: rgba(255, 0, 0, 1)"><strong>pet as Fish</strong></span>).swim !== undefined; //内部窄化逻辑</div>
<div>}</div>
<div>
<div>
<div>
<div>let pet = {</div>
<div> fly:()=>{}</div>
<div>}</div>
</div>
<div>if(isFish(pet)){</div>
<div> pet.swim() <strong><span style="color: rgba(255, 0, 0, 1)">//上面有了 pet is Fish,才不报错 Bird无swim方法</span></strong></div>
<div>}</div>
<div>else pet.fly();</div>
</div>
<div> </div>
<div><br>
<div><strong>判别的联合窄化(Discriminated unions)</strong></div>
<div>interface Circle{ // 圆</div>
<div> kind:'circle';</div>
<div> radius:number;</div>
<div>}</div>
<div>interface Square{ //方形</div>
<div> kind:'square',</div>
<div> sideLength:number;</div>
<div>}</div>
<div>type Shape = Circle | Square;</div>
<div>// 计算面积</div>
<div>function getArea(shape : Shape){</div>
<div> switch(shape.kind){</div>
<div> case 'circle':</div>
<div> return Math.PI * shape.radius ** 2; // ** 平方</div>
<div> case 'square':</div>
<div> return shape.sideLength ** 2;</div>
<div> }</div>
<div>}</div>
<div> </div>
<div><strong>Nevel</strong>:不应该出现的类型</div>
<div>
<div>interface Circle{ // 圆</div>
<div> kind:'circle';</div>
<div> radius:number;</div>
<div>}</div>
<div>interface Square{ //方形</div>
<div> kind:'square',</div>
<div> sideLength:number;</div>
<div>}</div>
<div>interface <strong>Trips</strong>{</div>
<div> kind:'trips';</div>
<div> value:number</div>
<div>}</div>
<div>
<div>
<div>type Shape = Circle | Square | <strong>Trips</strong>;</div>
<div>// 计算面积</div>
<div>function getArea(shape : Shape){</div>
<div> switch(shape.kind){</div>
<div> case 'circle':</div>
<div> return Math.PI * shape.radius ** 2; // ** 平方</div>
<div> case 'square':</div>
<div> return shape.sideLength ** 2;</div>
<div> <strong> default:</strong></div>
<div><strong> const _value:never = shape; // <span style="color: rgba(255, 0, 255, 1)">Error 不能将类型“Trips”分配给类型“never”。</span></strong></div>
<div><strong> return _value;</strong></div>
<div> }</div>
<div>}</div>
<div> </div>
<div><strong>inter 类型推导</strong></div>
<div><strong>// e.g 提取多层数组里的值</strong></div>
<div>
<div>type Flatterned<T> = T extends Array<infer V>?Flatterned<V>:T;</div>
<div>function flattern<T extends Array<any>>(arr:T):Array<Flatterned<T>>{</div>
<div> return (new Array()).concat(...arr.map(x=>Array.isArray(x)?flattern(x):x))</div>
<div>}</div>
<div>let val = flattern(]]]]]]);</div>
<div>console.log(val) //<span style="color: rgba(255, 0, 0, 1)"> </span></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div><br><br>
来源:https://www.cnblogs.com/liuxu-xrl/p/15401261.html
頁:
[1]