学习资源来自:
类与接口 · TypeScript 入门教程 (xcatliu.com)
TypeScript- 解决(tsc 不是内部或外部命令,也不是可运行的程序或批处理文件)问题 - sanyekui - 博客园 (cnblogs.com)
3.将环境安装好之后,就可以尝试构建第一个typeScript程序
function greeter(person: string) {
return 'Hello, ' + person
}
let user = 'Jane User'
document.body.innerHTML = greeter(user)
tsc greeter.ts
TypeScript Greeter
enum Color {
Red,
Green,
Blue,
}
let c: Color = Color.Green
默认情况下,从0开始为元素编号,可以手动指定成员的数值
enum Color {
Red = 1,
Green,
Blue,
}
let c: Color = Color.Green
console.log(c) // 2
全部采用手动赋值
enum Color {
Red = 1,
Green = 2,
Blue = 4,
}
let c: Color = Color.Blue
console.log(c) // 4
找出映射的名字
enum Color {
Red = 1,
Green,
Blue,
}
let colorName: string = Color[2]
console.log(colorName) // Green
let list: any[] = [1, true, "free"]
声明一个变量为任意值之后,对它的任何操作,返回的内容的类型都是任意值
在声明的之后,未指定其类型,就会被识别为任意值类型
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}
// 推断的返回值类型为never
function fail() {
return error("Something failed");
}
// 返回never的函数必须存在无法达到的终点
function infiniteLoop(): never {
while (true) {
}
}
let myFavoriteNumber: string | number;
myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
联合类型使用 | 分隔每个类型
let myFavoriteNumber: string | number; 的含义是允许 myFavoriteNumber 是string类型或者number类型,但是不能是其他类型
当TypeScript不确定一个联合类型的变量到底是哪个类型的时候,只能访问此联合类型中所有属性里共有的属性和方法
两种形式:
let someValue: any = 'this is a string'
let strLength: number = (someValue).length
let someValue: any = 'this is a string'
let strLength: number = (someValue as string).length
下面代码虽然没有指定类型,但是在编译的时候会报错,TypeScript 会在没有明确的指定类型的时候推测出一个类型,这就是类型推论
let myFavoriteNumber = 'seven';
myFavoriteNumber = 7;
如果在定义的时候没有赋值,不管之后有没有赋值,都会被推断为any类型而不被类型检查
① var和let声明与JavaScript中一致
② const 声明
③ let 和 const 的选择
④ 解构
解构数组
let input = [1, 2]
let [first, second] = input
console.log(first)
console.log(second)
利用解构交换两个变量的值
let input = [1, 2]
let [first, second] = input
;[first, second] = [second, first]
console.log(first)
console.log(second)
let input = [1, 2]
function f([first, second]: number[]) {
console.log(first)
console.log(second)
}
f(input)
使用剩余参数解构
let [first, ...rest] = [1, 2, 3, 4]
console.log(first)
console.log(rest)
let [first] = [1, 2, 3, 4]
console.log(first)
将不关心的元素省略
let [, second, , fourth] = [1, 2, 3, 4]
console.log(second)
解构对象
let o = {
a: 'foo',
b: 12,
c: 'bar',
}
let { a, b } = o
console.log(a)
console.log(b)
属性重命名
let o = {
a: 'foo',
b: 12,
c: 'bar',
}
let { a: name1, b: name2 } = o
console.log(name1)
console.log(name2)
默认值
参数默认值(如果函数没有传参数,就使用初始化列表中的值)
解构表达还是要尽量保持小而简单
⑤ 展开运算符
let first = [1, 2]
let second = [3, 4]
let bothPlus = [0, ...first, ...second, 5]
console.log(bothPlus) // [0, 1, 2, 3, 4, 5]
let defaults = { food: 'spicy', price: '$$', ambiance: 'noisy' }
let bothPlus = { ...defaults, food: 'rich' }
console.log(bothPlus) //
可选属性
① 有时候希望不要完全匹配一个形状,可以用可选属性
② 可选属性的含义就是该属性可以不存在
③ 但是仍然不允许添加未定义的属性
① 有时候我们希望一个接口允许有任意的属性,上面是使用 [propName: string]
定义了任意属性取string 类型的值
② 一旦定义了任意属性,那么确定属性和可选属性的类型都必须是它的类型的子集
③ 所以下面的案例中,如果任意属性中的值允许是string, 但是可选属性age的值是number,不是string的子属性,所以报错了
④ 一个接口中只能定义一个任意属性,如果接口中有多个类型的属性,则可以在任意属性中使用联合类型
① 有时候我们希望对象中的一些字段只能在创建的时候被赋值,就使用 readonly 定义只读属性
② 只读的约束存在于第一次给对象赋值的时候,而不是第一次给只读属性赋值的时候
③ 只读属性不能进行赋值(无法修改)
interface Point {
readonly x: number
readonly y: number
}
let p1: Point = { x: 10, y: 10 }
p1.x = 10 // 会报错,属性是只读属性
③ 只读属性在第一次初始化对象的时候,必须进行初始化
数组只读属性
let a: number[] = [1, 2, 3, 4]
// 限制数组是只读类型
let ro: ReadonlyArray = a
ro[0] = 1 // 报错
readonly 和 const
① 作为变量使用的话就用const
② 作为属性就使用 readonly
解决方法 ①
解决方法 ② :添加一个字符串索引签名
解决方法③ 将这个对象赋值给另一个变量,不会经过额外属性检查
①【类型 + 方括号】表示法
let fibonacci: number[] = [1, 1, 2, 3, 5];
② 数组的项中不允许出现其他类型
③ 数组中的一些方法的参数也会根据数组在定义时约定的类型进行限制
④ 可以使用数组泛型 Array
let fibonacci: Array = [1, 1, 2, 3, 5];
⑤ 用接口表示数组
interface NumberArr {
[index: number]: number
}
let fib: NumberArr = [1, 2, 3, 4]
用接口表示数组比较少见,但是经常用它表示类数组(伪数组)
使用普通数组不能定义为数组,所以使用接口的形式
常用的类数组都有自己的接口定义,比如 IArguments
, NodeList
, HTMLCollection
function sum() {
let args: IArguments = arguments
}
IArgument 是TypeScript定义好的类型,实际上就是
interface IArguments {
[index: number]: any;
length: number;
callee: Function;
}
⑥ any在数组中的应用:any表示数组中允许出现任意类型
let list: any[] = ['xcatliu', 25, { website: 'http://xcatliu.com' }];
① 函数声明:
function sum(x: number, y: number): number {
return x + y;
}
② 函数表达式
let mySum: (x: number, y: number) => number = function (x: number, y: number): number {
return x + y;
};
TypeScript 中的 => 和 ES6中的箭头不一样,TypeScript中,=>用来表示函数的定义,左边是输入类型,需要用括号括起来,右边是输出类型
③ 用接口定义函数的形状
interface SearchFunc {
(source: string, subString: string): boolean
}
let mySearch: SearchFunc
mySearch = function (source: string, subString: string) {
return source.search(subString) !== -1
}
用函数表达式或者接口定义函数时,对等号左侧进行类型限制,可以保证对函数名赋值时保证参数的个数,参数类型和返回值类型不变
④ 可选参数
⑤ 参数默认值
⑥ 剩余参数
function push(array: any[], ...items: any[]) {
items.forEach(function (item) {
array.push(item)
})
}
let a: any[] = []
push(a, 1, 2, 3)
⑦ 重载
function reverse(x: number): number
function reverse(x: string): string
function reverse(x: number | string): number | string | void {
if (typeof x === 'number') {
return Number(x.toString().split('').reverse().join(''))
} else if (typeof x === 'string') {
return x.split('').reverse().join('')
}
}
① 概念
类型断言含义:可以手动指定一个值类型
语法:值 as 类型 <类型>值
在 tsx(React 的 jsx 语法的 ts 版) 语法中必须使用前者
<类型>这种语法在ts中除了表示类型断言之外,也有可能是表示一个泛型
所以在使用断言的时候,统一使用 值 as 这样的语法
② 类型断言的用途
(1) 将一个联合类型断言为其中一个类型
(2)将一个父类断言为更加具体的子类
(3)将任何一个类型断言为any
(4)将as断言为一个具体的类型
总结
③ 类型断言的限制
interface Animal {
name: string
}
interface Cat {
name: string
run(): void
}
function testAnimal(animal: Animal) {
return animal as Cat
}
function testCat(cat: Cat) {
return cat as Animal
}
综上所述:
A
能够被断言为 B
,只需要 A
兼容 B
或 B
兼容 A
即可④ 双重断言
interface Cat {
run(): void
}
interface Fish {
swim(): void
}
function testCat(cat: Cat) {
return cat as any as Fish
}
⑤ 类型断言和类型转换
⑥ 类型断言和类型声明
类型断言
Animal
兼容 Cat
或 Cat
兼容 Animal
即可⑦ 类型断言和泛型
function getCacheData(key: string): T {
return (window as any).cache[key]
}
interface Cat {
name: string
run(): void
}
const tom = getCacheData('tom')
tom.run()
① 当使用第三方库时,我们需要引用它的声明文件,才能获得对应的代码补全,接口提示等功能
② 声明语句
③ 声明文件:把声明语句放到一个单独的文件中
文件以 .d.ts 为结尾 ,其他所有*.ts文件就可以获得 jQuery 的类型定义了
declare var jQuery: (selector: string) => any;
④ 第三方声明文件
npm install @types/jquery --save-dev
⑤ 书写声明文件
库的使用场景: