1、变量类型
基础变量
let isDone: boolean = false
let age: number = 20
let binaryNumber: number = 0b1111
let firstName: string = 'viking'
let message: string = `Hello, ${firstName}, age is ${age}`
let u: undefined = undefined
let n: null = null
let num: number = undefined
let notSure: any = 4
联合类型
let numberOrString: number | string = 234
numberOrString = 'abc'
数组
let arrOfNumbers: number[] = [1, 2, 3, 4]
arrOfNumbers.push(5)
let user: [string, number] = ['viking', 1]
2、接口
interface Person {
readonly id: number;
name: string;
age?: number;
}
let viking: Person = {
id: 1234,
name: 'viking',
}
3、函数及类型推断
// 函数声明
// function add(x: number, y: number, z: number = 10): number {
// if (typeof z === 'number') {
// return x + y + z
// } else {
// return x + y
// }
// }
// let result = add(2, 3, 5)
const add = function(x: number, y: number, z: number = 10): number {
if (typeof z === 'number') {
return x + y + z
} else {
return x + y
}
}
const add2: (x: number, y: number, z?: number) => number = add
4、类
类的使用和继承
class Animal {
name: string;
static categoies: string[] = ['mammal', 'bird']
static isAnimal(a) {
return a instanceof Animal
}
constructor(name: string) {
this.name = name
}
run() {
return `${this.name} is running`
}
}
console.log(Animal.categoies)
const snake = new Animal('lily')
console.log(Animal.isAnimal(snake))
class Dog extends Animal {
bark() {
return `${this.name} is barking`
}
}
const xiaobao = new Dog('xiaobao')
class Cat extends Animal {
constructor(name) {
super(name)
console.log(this.name)
}
run() {
return 'Meow, ' + super.run()
}
}
const maomao = new Cat('maomao')
类和接口
interface Radio {
switchRadio(): void;
}
interface Battery {
checkBatteryStatus();
}
// 继承接口
interface RadioWithBattery extends Radio {
checkBatteryStatus();
}
class Car implements Radio{
switchRadio() {
}
}
class Cellphone implements RadioWithBattery {
switchRadio() {
}
checkBatteryStatus() {
}
}
5、枚举
const enum Direction {
Up = 'UP',
Down = 'DOWN',
Left = 'LEFT',
Right = 'RIGHT',
}
const value = 'UP'
if (value === Direction.Up) {
console.log('go up!')
}
6、泛型
这里是难点也是重点,我会重点记录下 泛型的基本使用
function echo<T>(arg: T): T {
return arg
}
const result = echo(true)
感悟: 函数名后声明的T其实是一个标记可以是任意符号,也不一定是函数中传进来的参数类型,只是为了约定参数和返回值是一种类型,这块如果不是很理解可以自习看看下面两个例子.
function swap<T, U>(tuple: [T, U]): [U, T] {
return [tuple[1], tuple[0]]
}
const result2 = swap(['string', 123])
function echoWithArr<T>(arg: T[]): T[] {
console.log(arg.length)
return arg
}
const arrs = echoWithArr([1, 2, 3])
泛型和接口 下面例子就是使用接口来约束泛型,使传入的参数必须包含length属性
interface IWithLength {
length: number
}
function echoWithLength<T extends IWithLength>(arg: T): T {
console.log(arg.length)
return arg
}
const str = echoWithLength('str')
const obj = echoWithLength({ length: 10, width: 10})
const arr2 = echoWithLength([1, 2, 3])
实例思考:
接下来我们再思考一个问题,我们现在创建一个数组队列如下:
class Queue {
private data = [];
push(item) {
return this.data.push(item)
}
pop() {
return this.data.shift()
}
}
const queue = new Queue()
queue.push(1)
console.log(queue.pop().toFixed())
那么我们如何保证push进去的值一定是number,pop出来的值一定有toFixed函数???思考下
class Queue{
private data = [];
push(item: number) {
return this.data.push(item)
}
pop(): number {
return this.data.shift()
}
}
const queue = new Queue()
queue.push(1)
console.log(queue.pop().toFixed())
我们在这里给输入的值使用了类型,返回值也添加了类型,这样就不会有任何问题了,这里我们就要再深入思考下了,如果我需要创造一个数组队列需要传字符串类型呢,,,,再写个新队列定义字符串? 其实可以不用那么麻烦,我们用泛型改造下
class Queue<T> {
private data = [];
push(item: T) {
return this.data.push(item)
}
pop(): T {
return this.data.shift()
}
}
const queue = new Queue<number>()
queue.push(1)
console.log(queue.pop().toFixed())
const queue2 = new Queue<string>()
queue2.push('str')
console.log(queue2.pop().length)
这样我们就很轻松的解决了问题,只需要定义变量时传入泛型的类型就好了.
下面来看下变量和函数中泛型的使用:
interface KeyPair<T, U> {
key: T;
value: U;
}
let kp1: KeyPair<number, string> = { key: 123, value: "str" }
let kp2: KeyPair<string, number> = { key: 'test', value: 123 }
let arr: number[] = [1, 2, 3]
let arrTwo: Array<number> = [1, 2, 3]
interface IPlus<T> {
(a: T, b: T) : T
}
function plus(a: number, b: number): number {
return a + b;
}
function connect(a: string, b: string): string {
return a + b
}
const a: IPlus<number> = plus
const b: IPlus<string> = connect
7、其他
类型别名
// type aliases
type PlusType = (x: number, y: number) => number
function sum(x: number, y: number): number {
return x + y
}
const sum2: PlusType = sum
type NameResolver = () => string
type NameOrResolver = string | NameResolver
function getName(n: NameOrResolver): string {
if (typeof n === 'string') {
return n
} else {
return n()
}
}
类型断言
function getLength(input: string | number) : number {
// const str = input as String
// if (str.length) {
// return str.length
// } else {
// const number = input as Number
// return number.toString().length
// }
if((<string>input).length) {
return (<string>input).length
} else {
return input.toString().length
}
8、声明文件
在typescript中如果要使用第三方库,ts可能并不知道库是什么东西,也不清楚类型这时候就会抛出错误给我们,接下来我们就拿jQuery来举例
declare var jQuery:(sel:string) => any
jQuery('.foot')
做了声明后我们就可以正常使用了,通常这个声明我们会单独放在一个文件里 jQyery.d.ts
declare var jQuery:(sel:string) => any
注意:声明文件必须是以d.ts为后缀的,一般情况下ts会去自动解析项目中所有的d.ts文件
当然有些情况下我们依然无法自动获取声明文件怎么办呢?这里就需要我们再ts配置文件中声明,tsconfig.json里我们可以写ts编辑器的各种配置
{
"include": ["**/*"]
}
这下我们就解决了jQuery简单的声明了,但如果想正常使用jQuery中所有功能我们依然要声明很多内容,工作量真的很大... 其实社区早就为我们处理了很多常用的第三方库,我们只要搜索下载就可以使用了,这里是搜索地址