ts - 基础
TypeScript中文网 · TypeScript——JavaScript的超集
what
超集、扩展
扩展功能
类型批注和编译时类型检查
类型推断
类型擦除
接口
枚举
Mixin
泛型编程
名字空间
元组
类型
声明变量
var/let/const 变量名 [: 类型] [= 值];
类型推断
当类型没有给出时,TypeScript 编译器利用类型推断来推断类型。
如果由于缺乏声明而不能推断出类型,那么它的类型被视作默认的动态 any 类型。
var num = 2 ;
console .log ("num 变量的值为 " +num);
num = "12" ;
console .log (num);
类型断言
类型断言可以用来手动指定一个值的类型,即允许变量从一种类型更改为另一种类型。
语法格式:
<类型>值
或 值 as 类型
var str : string = '1'
var str2 : number = <number > <any >str
console .log (str2, typeof str2)
var str3 : number = str as any
console .log (str3, typeof str3)
联合类型
通过|
将变量设置多种类型,赋值时可以根据设置的类型来赋值。
var val :string |number
function disp (name:string |string [] ) {
if (typeof name == "string" ) {
console .log (name)
} else {
var i;
for (i = 0 ;i<name.length ;i++) {
console .log (name[i])
}
}
}
var arr :number []|string [];
元组
数组中元素的数据类型都一般是相同的(any[] 类型的数组可以不同),如果存储的元素数据类型不同,则需要使用元组。
var mytuple = [10 ,"String" ,false ];
访问控制修饰符
保护对类、变量、方法和构造方法的访问。
public(默认) : 公有,可以在任何地方被访问。
protected : 受保护,可以被其自身以及其子类访问。
private : 私有,只能被其定义所在的类访问。
只读属性
interface Point {
readonly x : number ;
readonly y : number ;
}
ReadonlyArray
let a : number [] = [1 , 2 , 3 , 4 ];
let ro : ReadonlyArray <number > = a;
ro[0 ] = 12 ;
ro.push (5 );
ro.length = 100 ;
a = ro;
a = ro as number [];
readonly vs const
做为变量使用的话用 const,若做为属性则使用readonly。
函数
返回值
function function_name ( )[:return_type] {
return 'value' ;
}
可选参数
定义了参数,必须传入参数,除非将这些参数设置为可选,可选参数使用问号标识 ?
可选参数必须跟在必需参数后面。
function buildName (firstName: string , lastName: string ) {
return firstName + " " + lastName;
}
let result1 = buildName ("Bob" );
let result2 = buildName ("Bob" , "Adams" , "Sr." );
let result3 = buildName ("Bob" , "Adams" );
function buildName (firstName: string , lastName?: string ) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
let result1 = buildName ("Bob" );
let result2 = buildName ("Bob" , "Adams" , "Sr." );
let result3 = buildName ("Bob" , "Adams" );
剩余参数
不知道要向函数传入多少个参数,剩余参数语法允许我们将一个不确定数量的参数 作为一个数组 传入。
函数的最后一个命名参数 restOfName
以 ...
为前缀 ,它将成为一个由剩余参数组成的数组,索引值从0(包括)到 restOfName.length(不包括)
function buildName (firstName: string , ...restOfName: string [] ) {
return firstName + " " + restOfName.join (" " );
}
let employeeName = buildName ("Joseph" , "Samuel" , "Lucas" , "MacKinzie" );
泛型
泛型的语法是 <>
里写类型参数,一般可以用 T
来表示。
泛型中的 T 就像一个占位符、或者说一个变量,在使用的时候可以把定义的类型像参数一样传入,它可以原封不动地输出。
输入和输出的类型统一,且可以输入输出任何类型。
function print<T>(arg :T):T {
console .log (arg)
return arg
}
泛型约束
操作某类型的一组值,编译器并不能证明每种类型具有什么样的属性报错了。
function loggingIdentity<T>(arg : T): T {
console .log (arg.length );
return arg;
}
需要列出对于T的约束要求
interface Lengthwise {
length : number ;
}
function loggingIdentity<T extends Lengthwise >(arg : T): T {
console .log (arg.length );
return arg;
}
枚举
数字枚举
枚举成员值
每个枚举成员都有一个 name 和一个 value。数字枚举成员值的默认类型是 number 类型。也就是说,每个成员的值都是一个数字
除了让 TypeScript 为我们指定枚举成员的值之外,我们还可以手动赋值
通过等号的显式赋值称为 initializer。如果枚举中某个成员的值使用显式方式赋值,但后续成员未显示赋值, TypeScript 会基于当前成员的值加 1 作为后续成员的值
枚举成员名称的转换
TypeScript 手册使用以大写字母开头的驼峰式名称。
反向映射
数字枚举成员还具有了反向映射 ,从枚举值到枚举名字
enum Direction {
Up ,
Down ,
Left ,
Right
}
console .log (Direction );
enum DirectionInit {
Up = 1 ,
Down ,
Left ,
Right
}
console .log (DirectionInit );
字符串枚举
enum Direction {
Up = 'UP' ,
Down = 'DOWN' ,
Left = 'LEFT' ,
Right = 'RIGHT'
}
console .log (Direction )
const枚举
避免在额外生成的代码上的开销和额外的非直接的对枚举成员的访问
const enum Directions {
Up ,
Down ,
Left ,
Right
}
console .log (Directions .Up )
console .log (Directions )
外部枚举
declare enum Enum {
A = 1 ,
B,
C = 2
}
外部枚举和非外部枚举之间有一个重要的区别,在正常的枚举里,没有初始化方法的成员被当成常数成员。 对于非常数的外部枚举而言,没有初始化方法时被当做需要经过计算的。
接口
接口是一系列抽象方法的声明,是一些方法特征的集合,这些方法都应该是抽象的,需要由具体的类去实现,然后第三方就可以通过这组抽象方法调用,让具体的类执行具体的方法。
interface interface_name {
}
联合类型接口
interface RunOptions {
program :string ;
commandline :string []|string |(()=> string );
}
var options :RunOptions = {program :"test1" ,commandline :"Hello" };
console .log (options.commandline )
options = {program :"test1" ,commandline :["Hello" ,"World" ]};
console .log (options.commandline [0 ]);
console .log (options.commandline [1 ]);
options = {program :"test1" ,commandline :()=> {return "**Hello World**" ;}};
var fn :any = options.commandline ;
console .log (fn ());
接口数组
interface namelist {
[index :number ]:string
}
var list2 :namelist = ["Google" ,"Runoob" ,"Taobao" ]
接口继承
通过其他接口来扩展自己
允许接口继承多个接口。
继承使用关键字 extends。
继承的各个接口使用逗号 , 分隔。
Child _interface_name extends super_interface1_name[, super_interface2_name,…,super_interfaceN_name]
interface Person {
age :number
}
interface Musician extends Person {
instrument :string
}
var drummer = <Musician >{};
drummer.age = 27
drummer.instrument = "Drums"
console .log ("年龄: " +drummer.age )
console .log ("喜欢的乐器: " +drummer.instrument )
类和接口
类可以实现接口,使用关键字 implements,并将 interest 字段作为类的属性使用。
interface ILoan {
interest :number
}
class AgriLoan implements ILoan {
interest :number
rebate :number
constructor (interest:number ,rebate:number ) {
this .interest = interest
this .rebate = rebate
}
}
var obj = new AgriLoan (10 ,1 )
console .log ("利润为 : " +obj.interest +",抽成为 : " +obj.rebate )
类型别名
类型别名会给一个类型起个新名字。 类型别名有时和接口很像,但是可以作用于原始值,联合类型,元组以及其它任何你需要手写的类型。
不会新建一个类型 - 它创建了一个新 名字来引用那个类型。 给原始类型起别名通常没什么用,尽管可以做为文档的一种形式使用。
type Name = string ;
type NameResolver = () => string ;
type NameOrResolver = Name | NameResolver ;
function getName (n: NameOrResolver ): Name {
if (typeof n === 'string' ) {
return n;
}
else {
return n ();
}
}
interface vs type
相同点
定义一个对象或函数
type addType = (num1:number ,num2:number ) => number
interface addType {
(num1 :number ,num2 :number ):number
}
const add :addType = (num1, num2 ) => {
return num1 + num2
}
允许继承(extends
interface Person {
name : string
}
interface Student extends Person {
grade : number
}
type Person = {
name : string
}
type Student = Person & { grade : number }
type Person = {
name : string
}
interface Student extends Person {
grade : number
}
interface Person {
name : string
}
type Student = Person & { grade : number }
不同点
声明基本类型、联合类型、交叉类型、元组
type Name = string
type arrItem = number | string
const arr : arrItem[] = [1 ,'2' , 3 ]
type Person = {
name : Name
}
type Student = Person & { grade : number }
type Teacher = Person & { major : string }
type StudentAndTeacherList = [Student , Teacher ]
const list :StudentAndTeacherList = [
{ name : 'lin' , grade : 100 },
{ name : 'liu' , major : 'Chinese' }
]
合并重复声明
interface Person {
name : string
}
interface Person {
age : number
}
const person : Person = {
name : 'lin' ,
age : 18
}
type Person = {
name : string
}
type Person = {
age : number
}
命名空间
解决重名问题。
命名空间定义了标识符的可见范围,一个标识符可在多个名字空间中定义,它在不同名字空间中的含义是互不相干的。这样,在一个新的名字空间中可定义任何标识符,它们不会与任何已有的标识符发生冲突,因为已有的定义都处于其他名字空间中。
语法格式
namespace SomeNameSpaceName {
export interface ISomeInterfaceName { }
export class SomeClassName { }
}
SomeNameSpaceName .SomeClassName ;
文件引用
如果一个命名空间在一个单独的 TypeScript 文件中,则应使用三斜杠 /// 引用它,语法格式如下:
实例
namespace Drawing {
export interface IShape {
draw ();
}
}
namespace Drawing {
export class Circle implements IShape {
public draw ( ) {
console .log ("Circle is drawn" );
}
}
}
namespace Drawing {
export class Triangle implements IShape {
public draw ( ) {
console .log ("Triangle is drawn" );
}
}
}
function drawAllShapes (shape:Drawing.IShape ) {
shape.draw ();
}
drawAllShapes (new Drawing .Circle ());
drawAllShapes (new Drawing .Triangle ());
嵌套命名空间
将命名空间定义在另外一个命名空间里头。
namespace namespace_name1 {
export namespace namespace_name2 {
export class class_name { }
}
}
成员的访问使用点号 . 来实现
new namespace_name1.namespace_name2 .class_name ()
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
2022-03-31 vscode - plugs - koroFileHeader