TypeScript阶段学习
TypeScript
首先来了解一下TypeScript
TypeScript是JavaScript的,带有类型的超集,它可以编译成纯JavaScript。
TypeScript可以在任何浏览器、任何计算机和任何操作系统上运行,并且是开源的。
- 超集:支持所有的js,并在此基础上添加了额外的功能
- 有类型的:js类型是动态的,只有在运行时可知是什么类型,并且类型是变化的;TS要求是有类型的,即使没有,给与初始值的时候类型也会确定,类型与值不一致时会报错。TS是静态类型的编程语言,JS是动态类型的编程语言。静态类型编译期做类型检查;动态类型执行期做类型检查。
- 编译:说明TS本身不能在浏览器或者node环境中运行,需要编译器编译为js代码才可以运行
所以举个恰当的例子,就好比JavaScript和Jquery的关系,TypeScript做的也是让JavaScript这门语言越来越规范,越来越好用的作用。在平常的开发中完全可以用TypeScript来代替JavaScript.
安装TypeScript
- npm安装
> npm install -g typescript
- VScode
在插件商店下载即可。
编译
在编译时,发现错误,抛出错误。
tsc .\index.ts
使用
tsc
对文件进行编译(默认生成ES3版本的js文件)
监听编译
tsc .\index.ts -w
生成tsconfig.json
tsc --init
常用配置
示例:
tsconfig.json
示例文件:
- 使用"files"属性
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
},
"files": [
"core.ts",
"sys.ts",
"types.ts",
"scanner.ts",
"parser.ts",
"utilities.ts",
"binder.ts",
"checker.ts",
"emitter.ts",
"program.ts",
"commandLineParser.ts",
"tsc.ts",
"diagnosticInformationMap.generated.ts"
]
}
- 使用
"include"
和"exclude"
属性
{
"compilerOptions": {
"module": "system",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"outFile": "../../built/local/tsc.js",
"sourceMap": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
注意
*
匹配0或多个字符(不包括目录分隔符)?
匹配一个任意字符(不包括目录分隔符)**/
递归匹配任意子目录
使用"include"
引入的文件可以使用"exclude"
属性过滤。
常用编译选项:
选项 | 类型 | 默认值 | 描述 |
---|---|---|---|
--allowJs | boolean | false | 允许编译javascript文件。 |
--charset | string | "utf8" | 输入文件的字符集。 |
--checkJs | boolean | false | 在 .js 文件中报告错误。与 --allowJs 配合使用。 |
--init | 初始化TypeScript项目并创建一个 tsconfig.json 文件。 |
||
--module -m | string | 指定生成哪个模块系统代码: "None" , "CommonJS" , "AMD" , "System" , "UMD" , "ES6" 或 "ES2015" 。 |
|
--outDir | string | 重定向输出目录。 | |
--outFile | string | 将输出文件合并为一个文件 | |
--target -t | string | "ES3" | 指定ECMAScript目标版本 "ES3" (默认), "ES5" , "ES6" / "ES2015" , "ES2016" , "ES2017" 或 "ESNext" 。 |
--watch -w | 在监视模式下运行编译器。 |
-
tsc index.js -w
自动监视当前ts文件,并进行编译 -
tsc -w
自动编译所有的文件,前提是有配置文件tsconfig.json
-
tsconfig.json
:ts编译器的配置文件,ts编译器可以根据它的信息对代码进行编译。tsc --init
-
include:"src/**/*"
用来指定哪些ts文件被编译 -
exclude
用来指定被排除的文件 -
compilerOptions
:编译器选项target
用来指定ts被编译为的js的版本module
用来指定使用模块化的规范outDir
用来指定编译后文件所在的目录removeComments
是否移除注释
基础数据类型
boolean,string,number,[]
- 隐式类型:ts根据变量的值来推断类型,代码的写法类似于js,但不能用其他类型的值赋值
- 显示类型:用
: 类型
来显示规定变量的类型
1. 布尔值
let isDone: boolean = false
2. 数字
和JavaScript一样,TypeScript里的所有数字都是浮点数。 这些浮点数的类型是 number
。 除了支持十进制和十六进制字面量,TypeScript还支持ECMAScript 2015中引入的二进制和八进制字面量。
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
3. 字符串
JavaScript程序的另一项基本操作是处理网页或服务器端的文本数据。 像其它语言里一样,我们使用 string
表示文本数据类型。 和JavaScript一样,可以使用双引号( "
)或单引号('
)表示字符串。
let name: string = "bob";
name = "smith";
你还可以使用模版字符串,它可以定义多行文本和内嵌表达式。 这种字符串是被反引号包围,并且以${ expr }
这种形式嵌入表达式
let name: string = `Gene`;
let age: number = 37;
let sentence: string = `Hello, my name is ${ name }.
I'll be ${ age + 1 } years old next month.`;
4. 数组
TypeScript像JavaScript一样可以操作数组元素。 有两种方式可以定义数组。 第一种,可以在元素类型后面接上 []
,表示由此类型元素组成的一个数组:
let list: number[] = [1, 2, 3];
第二种方式是使用数组泛型,Array<元素类型>
:
let list: Array<number> = [1, 2, 3];
特殊数据类型
undefined,null,Object,any,void
1. Any
有时候,我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容,比如来自用户输入或第三方代码库。 这种情况下,我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any
类型来标记这些变量:
let notSure: any = 4;
notSure = "maybe a string instead";
notSure = false; // okay, definitely a boolean
在对现有代码进行改写的时候,any
类型是十分有用的,它允许你在编译时可选择地包含或移除类型检查。 你可能认为 Object
有相似的作用,就像它在其它语言中那样。 但是 Object
类型的变量只是允许你给它赋任意值 - 但是却不能够在它上面调用任意的方法,即便它真的有这些方法:
let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)
let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.
2. Void
某种程度上来说,void
类型像是与any
类型相反,它表示没有任何类型。 当一个函数没有返回值时,你通常会见到其返回值类型是 void
:
function warnUser(): void {
console.log("这是我的警告信息");
}
声明一个void
类型的变量没有什么大用,因为你只能为它赋予undefined
和null
:
let unusable: void = undefined;
3. Null和Undefined
TypeScript里,undefined
和null
两者各自有自己的类型分别叫做undefined
和null
。 和 void
相似,它们的本身的类型用处不是很大:
// 我们只能给他们各自赋值undefined和null
let u: undefined = undefined;
let n: null = null;
默认情况下null
和undefined
是所有类型的子类型。 就是说你可以把 null
和undefined
赋值给number
类型的变量。
4. Object
object
表示非原始类型,也就是除number
,string
,boolean
,symbol
,null
或undefined
之外的类型。
使用object
类型,就可以更好的表示像Object.create
这样的API。例如:
declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK
create(42); // Error
create("string"); // Error
create(false); // Error
create(undefined); // Error
元组Tuple
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为 string
和number
类型的元组。
// Declare a tuple type
let x: [string, number];
// Initialize it
x = ['hello', 10]; // OK
// Initialize it incorrectly
x = [10, 'hello']; // Error
当访问一个已知索引的元素,会得到正确的类型:
console.log(x[0].substr(1)); // OK
console.log(x[1].substr(1)); // Error, 'number' does not have 'substr'
当访问一个越界的元素,会使用联合类型替代:
x[3] = 'world'; // OK, 字符串可以赋值给(string | number)类型
console.log(x[5].toString()); // OK, 'string' 和 'number' 都有 toString
x[6] = true; // Error, 布尔不是(string | number)类型
联合类型
每个变量可以有多个类型,但是不想使用any破坏类型检查,就可以使用联合类型
Type1|Type2|Type3
var val:string:number
val = 12
val = "hi"
将联合类型作为函数参数使用。
function fn(name:string|string[]){
if(typeof name == "string") {
console.log(name)
} else {
for(var i = 0;i<name.length;i++) {
console.log(name[i])
}
}
}
- 自定义类型:
type NumStr = number | string;
var a:NumStr="hello";
var c:"on"|"off"="on"
接口
检查对象中的属性是否符合规范,用来规范对象中应该都有哪些属性。名称以及类型
- 利用接口调查对象是否规范
interface Post{ title:string, author:string } var post:Post={ title:"三体", author:"六字" }
- 利用接口检查函数是否规范
- 属性:
var sites = {
site1:"hello",
site2:"Google"
}
- 方法:
var sites = {
site1:"runboob",
site2:"google",
sayHello:funcation(){} //类型模板
}
sites.sayHello = funcation(){return "hello"} //直接写报错
- 将对象作为参数传递给函数
funcation fn(obj:{site1:string ,site2:string}){
console.log(obj.site1)
}
var sites={
site1:"Runoob",
site2:"Google",
}
fn(sites)
函数
和JavaScript一样,TypeScript函数可以创建有名字的函数和匿名函数。 你可以随意选择适合应用程序的方式,不论是定义一系列API函数还是只使用一次的函数。
// 有名字的函数
function add(x, y) {
return x + y;
}
// 匿名函数
let myAdd = function(x, y) { return x + y; };
1. 函数类型
为函数定义类型
function add(x: number, y: number): number {
return x + y;
}
let myAdd = function(x: number, y: number): number { return x + y; };
注意:
这里为x,y设定了数据类型为number,且返回值类型同样是number
书写完整的函数类型
let myAdd: (x: number, y: number) => number =
function(x: number, y: number): number { return x + y; };
2.可选参数和默认参数
可选参数
TypeScript里的每个函数参数都是必须的。 这不是指不能传递 null
或undefined
作为参数,而是说编译器检查用户是否为每个参数都传入了值。 编译器还会假设只有这些参数会被传递进函数。 简短地说,传递给一个函数的参数个数必须与函数期望的参数个数一致。
function buildName(firstName: string, lastName: string) {
return firstName + " " + lastName;
}
let result1 = buildName("Bob"); // error, 少参数
let result2 = buildName("Bob", "Adams", "Sr."); // error, 多参数
let result3 = buildName("Bob", "Adams"); // 正确
JavaScript里,每个参数都是可选的,可传可不传。 没传参的时候,它的值就是undefined
。 在TypeScript里我们可以在参数名旁使用 ?
实现可选参数的功能。 比如,我们想让last name是可选的:
function buildName(firstName: string, lastName?: string) {
if (lastName)
return firstName + " " + lastName;
else
return firstName;
}
let result1 = buildName("Bob"); // ?起作用了,所以没有报错
let result2 = buildName("Bob", "Adams", "Sr."); // error, 实参多于形参
let result3 = buildName("Bob", "Adams"); // ?起作用,正确
可选参数必须跟在必须参数后面。 如果上例我们想让first name是可选的,那么就必须调整它们的位置,把first name放在后面。
默认参数
在TypeScript里,我们也可以为参数提供一个默认值当用户没有传递这个参数或传递的值是undefined
时。 它们叫做有默认初始化值的参数。 让我们修改上例,把last name的默认值设置为"Smith"
。
function buildName(firstName: string, lastName = "Smith") {
return firstName + " " + lastName;
}
let result1 = buildName("Bob"); // 提供一个实参, 返回 "Bob Smith"
let result2 = buildName("Bob", undefined); // 仍然正确, 也返回"Bob Smith"
let result3 = buildName("Bob", "Adams", "Sr."); // error, 实参大于形参
let result4 = buildName("Bob", "Adams"); // 正确,返回"Bob Adams"
在所有必须参数后面的带默认初始化的参数都是可选的,与可选参数一样,在调用函数的时候可以省略。 也就是说可选参数与末尾的默认参数共享参数类型。
function buildName(firstName: string, lastName?: string) {
// ...
}
和
function buildName(firstName: string, lastName = "Smith") {
// ...
}
共享同样的类型(firstName: string, lastName?: string) => string
。 默认参数的默认值消失了,只保留了它是一个可选参数的信息。