强类型与弱类型
强类型与弱类型属于类型安全方面。
强类型有更强的类型约束,而弱类型几乎没有什么约束。
强类型中不允许有任意隐式类型的转换,弱类型中允许任意的数据隐式类型的转换。
静态类型语言与动态类型语言
静态类型语言与动态类型语言属于类型检查方面。
静态类型语言:一个变量申明时,它的类型就是明确的。申明过后它的类型就不能够更改。在编译的时候去做一个类型的检查
动态类型语言:在运行阶段才能明确变量类型,而且变量类型可以随时发生改变。动态语言中的变量没有类型,变量中存放的值是有类型的。比如var等,js就是动态类型语言。
弱类型语言可能带来的问题:程序异常部分需要等到程序运行到那里的时候才会发现;类型不明确会造成函数功能发生改变;对对象索引器发生影响等
Flow
类型注解:
可以为变量添加var a:number = 0
为函数参数添加function fn (a: number) {}
为函数返回值添加function fn (a: number):number {}
,若函数没有返回值则function fn (a: number): void {}
数据类型
var a: string = ''
var b: number = 0 || NaN
var c: boolean = true || false
var d: null = null
var e: void = undefined
var f: symbol: Symbol()
数组类型
var arr:Array<number> = [1,2]//表示由全部都是数字的数组
var arr2: number[] = [1,2]//同上
const foo: [String, number] = ['a', 1]//固定长度的数组(元组)
对象类型
//必须具有这两个key
const obj: {foo: string, bar: number} = {foo: '111', bar: 10}
//foo这个字段可有可无
const obj: {foo?: string, bar: number} = {foo: '111', bar: 10}
//key必须为string类型,value也必须为string类型
const obj: { [string]: string } = {'abc': '1111'}
函数类型
//限制参数
function sum (a: number, b: number) {
return a + b
}
//限制返回参数
function sum2 (a: number, b: number): number {
return a + b
}
//限制回调函数的参数和返回值的类型
function foo (callback: (string, number) => void) {
callback('string', 100)
}
特殊类型
//字面量类型,申明的值只能是定义的值,不能是其他的
const a: 'foo' = 'foo'
const type: 'error' | 'warning' | 'danger' = 'error'
//变量可以是其中一个
const b: string | number = 10
type StringOrNumber = string | number
const b1: StringOrNumber = 10
//maybe类型
const a: ?number = 10 //或者是null undefined
Mixed与Any
mixed是强类型,any是弱类型
//传入的值可以是任意值
function passMixed(value: mixed) {
//内部若没有明确value的类型是什么样的情况下,value不能调用任何类型的方法
if(typeof value === 'string') {
}
}
//传入的值可以是任意值
function passMixed2(value: any) {
//不需要明确value的类型,如果传进来是number则直接可以做乘法之类的运算,是string的话直接可以调用string类型的方法
}
TypeScript
ts其实是js的超集,包括了js,类型系统,es6+,最终编译成了js。
tsc --init可以生成ts的配置文件,从而可以配置整个项目
标准库就是内置对象对应的一个申明文件
语言类型
const a: number = 100
const b: string = '111'
const c: boolean = true
//注意ts是允许一开始的值是为空的,但是严格模式下不允许
const d: string = null
const e: void = undefined
const f: null = null
const g: undefined = undefined
const h: symbol = Symbol()
Object类型
ts中的object类型是可以接收对象,数组,函数的。
const foo: object = {}
const obj: { key: string, bar: number } = { key: 'text', bar: 10 }
数组类型
const arr: Array<number> = [1,2]
const arr2: number[] = [1,2]
元组类型
元组类型就是一个明确了元素数量和元素每一个值的类型的数组
const tuple: [string, number] = ['11', 2]
const [name, age] = tuple;
枚举类型enum
enum PostState {
Draf = 0,
Unpublished = 1,
published = 2
}
const post = {
status: PostState.published
}
//数字枚举:假如只有第一个值是有默认值的,那么后面的值会依次累加1
enum PostState {
Draf = 3,
Unpublished,
published
}
//字符串枚举:由于无法加1,所以每个值都需要附上默认值
enum PostState2 {
Draf = '2',
Unpublished = '3',
published = '4'
}
const enum PostState2 {
Draf = '2',
Unpublished = '3',
published = '4'
}
函数类型
可选参数必须在最后
//这里传入的参数数量也必须一致
function fn (a: number, b: number): string {
return 'aaaa'
}
//可选参数
function fn (a: number, b?: number): string {
return 'aaaa'
}
//或者用es6的参数默认值,这样这个参数也变成可有可无的了
function fn (a: number, b: number = 10): string {
return 'aaaa'
}
//任意参数
function fn (a: number, b: number, ...res: number[]): string {
return 'aaaa'
}
//函数表达式
const abc: (a: number) => string = function (a: number): string {
return '123'
}
任意类型
语法上不会报错
function stringfy (value: any) {
return JSON.stringify(value)
}
隐式类型
let age = 10
//上面age定义的时候已经隐式推断成了number类型,所以下面用string赋值会报错
age = 'aaa'
let a
//由于a没有定义任何类型,所以a在下面被赋值成什么形式都不会报错
a = 10
a = 'string'
类型断言
明确告诉ts这个值是什么类型的
const nums = [1,2,3,4]
const res = nums.find(i => i>0)
const num1 = res as number
const num2 = <number>res //jsx中不能使用
接口
用来去约定对象的结构
定义接口的关键字interface
interface Post {
title: string
content?: string
readonly summery: string //只读成员,只读成员被定义之后,初始化之后不可改变
}
function printPost (post: Post) {
console.log(post.title)
console.log(post.content)
}
const hello: Post = {
title: '1',
content: '2',
summery: '3', //初始化之后不可改变
}
//当定义的成员key值不确定的时候
interface Cache {
[key: string]: string
}
类
描述一类事物的抽象特征
class Person {
name: string
age: number
constructor(name: string, age: number) {
this.name = name
this.age = age
}
sayHi (msg: string): void {
console.log(msg)
}
}
类的访问修饰符
public
private: 类的私有属性,只能在类中进行访问
protected : 只允许在子类中访问
class Person {
public name: string
private age: number //类的私有属性,只能在类中进行访问
protected gender: boolean //只允许在此类中访问
constructor(name: string, age: number) {
this.name = name
this.age = age
this.gender = true
}
sayHi (msg: string): void {
console.log(msg)
console.log(this.age)
}
}
class student extends Person {
constructor (name: string, age: number) {
super(name, age)
console.log(this.gender) //true 可以访问
}
}
const tom = new Person('tom', 8)
console.log(tom.name)
// tom.genger 不能访问
// tom.age 不能访问
class Student extends Person {
//外部无法调用此构造函数
private constructor (name: string, age: number) {
super(name, age)
console.log(this.gender) //true 可以访问
}
//静态函数,挂载到当前类上
static create (name: string, age: number) {
return new Student(name, age)
}
}
const merrag = Student.create('merry', 10)
类与接口
implements
继承这个接口
interface EatAndRun {
eat(food: string): void
run(distance: number): void
}
interface Eat {
eat(food: string): void
}
interface Run {
run(distance: number): void
}
class Person implements Eat, Run {
eat (food: string): void {
console.log(`优雅的进餐${food}`)
}
run (distance: number) {
console.log(`直立行走${distance}`)
}
}
class Animal implements EatAndRun {
eat (food: string): void {
console.log(`呼噜呼噜的吃${food}`)
}
run (distance: number) {
console.log(`爬行${distance}`)
}
}
抽象类
abstract
定义抽象类 以及 抽象类中的抽象方法。
如果抽象类中定义了抽象方法,那么子类一定要有这个抽象方法。
abstract class Animal {
eat (food: string): void {
console.log(`呼噜呼噜的吃${food}`)
}
//抽象方法不需要方法体
abstract run (distance: number): void
}
class Dog extends Animal {
run(distance: number): void {
console.log(distance)
}
}
//这样子类就有了父类中的方法,以及自己的方法
const d = new Dog()
d.eat('grass')
d.run(11)
泛型
在定义方法,类或者接口的时候,没有指定特定的类型,在使用的时候才有具体的类型。
function createNumberArray (length: number, value: number): number[] {
const arr = Array<number>(length).fill(value)
return arr
}
function createStringArray (length: number, value: string): string[] {
const arr = Array<string>(length).fill(value)
return arr
}
const res = createNumberArray(3, 100)
console.log(res) //[100, 100, 100]
function createArray<T> (length: number, value: T): T[] {
const arr = Array<T>(length).fill(value)
return arr
}
const res2 = createArray<number>(3, 100)
console.log(res) //[100, 100, 100]
类型声明
declare
一个成员在定义的时候,由于种种原因没有明确的一个类型,使用它的时候可以单独的给它设置一个声明。