Study Notes
本博主会持续更新各种前端的技术,如果各位道友喜欢,可以关注、收藏、点赞下本博主的文章。
类型系统
强类型语言
强类型指的是程序中表达的任何对象所从属的类型都必须能在编译时刻确定。
对于强类型语言,一个变量不经过强制转换,它永远是这个数据类型,不允许隐式的类型转换。
假设定义了一个 double 类型变量 a,不经过强制类型转换那么程序 int b = a 是无法通过编译。
// 编译失败
double a;
int b = a;
let a = '100';
let b = 50;
console.log(a - b);
// 50 将a隐式转换为Number
console.log(a + b);
// 10050 将b隐式转换为String
npm install --save-dev @babel/core @babel/cli @babel/preset-flow
{
"presets": ["@babel/preset-flow"]
}
babel 输入需剔除的文件或文件夹路径 -d 输出文件夹
npm install --save-dev flow-bin
{
"scripts": {
"flow": "flow"
}
}
npm run flow init
npm run flow
/**
* Type Annotations(类型注解)
* flow
*/
// 参数添加类型注解
function add(x: number, y: number) {
return x + y;
}// 正确
add(100, 100);
// 报错
// add('100', 100);
// 声明基本类型数据时添加类型注解
let num: number = 100;
// 正确
// num = '100';
// 报错// 声明函数时添加类型注解
function sum(): number {
return 100;
// 只能返回number类型数据
// return '100';
// 报错
}
/**
* Primitive Types(原始类型)
* @flow
*/
const bol: boolean = true;
// false Boolean(0) Boolean(1)const str: string = 'abs';
const nums: number = 1;
// 3.14 NaN Infinityconst emt: null = null;
const un: void = undefined;
const syb: symbol = Symbol();
// Symbol.isConcatSpreadable
/**
* Literal Types(文字类型)
* @flow
*/
function acceptsTwo(value: 2) {
// ...
}acceptsTwo(2);
// Works!
// $ExpectError
acceptsTwo(3);
// Error!
// $ExpectError
acceptsTwo('2');
// Error!
/**
* Literal Types(文字类型)
* @flow
*/
function getColor(name: 'success' | 'warning' | 'danger') {
switch (name) {
case 'success':
return 'green';
case 'warning':
return 'yellow';
case 'danger':
return 'red';
}
}getColor('success');
// Works!
getColor('danger');
// Works!
// $ExpectError
getColor('error');
// Error!
/**
* Mixed Types(混合类型)
* @flow
*/
function stringify(value: mixed) {
// ...
}stringify('foo');
stringify(3.14);
stringify(null);
stringify({});
/**
* Mixed Types(混合类型)
* @flow
*/
function stringify(value: mixed) {
return '' + value;
// Error!
}stringify('foo');
/**
* Mixed Types(混合类型)
* @flow
*/
function stringify(value: mixed) {
if (typeof value =https://www.it610.com/article/=='string') {
return '' + value;
// Works!
} else {
return '';
}
}stringify('foo');
使用any是完全不安全的,应尽可能避免使用。/**
* Any Types(任何类型)
* @flow
*/
function division(one: any, two: any): number {
return one / two;
}division(1, 2);
// Works.
division('1', '2');
// Works.
division({}, []);
// Works.
/**
* Maybe Types(可能类型)
* @flow
*/
function acceptsMaybeNumber(value: ?number) {
// ...
}acceptsMaybeNumber(42);
// Works!
acceptsMaybeNumber();
// Works!
acceptsMaybeNumber(undefined);
// Works!
acceptsMaybeNumber(null);
// Works!
acceptsMaybeNumber('42');
// Error!
function concat(a: string, b: string): string {
return a + b;
}concat('foo', 'bar');
// Works!
// $ExpectError
concat(true, false);
// Error!function method(func: (...args: Array) => any) {
func(1, 2);
// Works.
func('1', '2');
// Works.
func({}, []);
// Works.
}method(function (a: number, b: number) {
// ...
});
/**
* Object Types(对象类型)
* @flow
*/
let obj1: { foo: boolean } = { foo: true };
// Works.
obj1.bar = true;
// Error!
obj1.foo = 'hello';
// Error!let obj2: {
foo: number,
bar: boolean,
baz: string,
} = {
foo: 1,
bar: true,
baz: 'three',
};
// Works.let obj3: { foo: string, bar: boolean };
obj3 = { foo: 'foo', bar: true };
obj3 = { foo: 'foo' };
npm i typescript -D
npm i ts-node -D
ts-node 文件路径
const test = (name: string) => console.log(`hello ${name}`);
test('typescript');
tsc index
var test = function (name) {
return console.log('hello ' + name);
};
test('typescript');
tsc --init
let isDone: boolean = true;
let decLiteral: number = 6;
let hexLiteral: number = 0xf00d;
let binaryLiteral: number = 0b1010;
let octalLiteral: number = 0o744;
let str: string = 'bob';
str = 'smith';
str = `smith${str}`;
let list: number[] = [1, 2, 3];
let list1: Array = [1, 2, 3];
let x: [string, number];
x = ['hello', 10];
// OK
// x = [10, 'hello'];
// Error
enum Color {
Red = 8,
Green,
Blue,
} // 默认0,1,2
let c: Color = Color.Green;
let cName: string = Color[9];
console.log(c);
console.log(cName);
// 9
// Green
let notSure: any = 4;
notSure = 'maybe a string instead';
notSure = false;
notSure = 1;
function warnUser(): void {
console.log('This is my warning message');
}
let unusable: void = undefined;
let u: undefined = undefined;
let n: null = null;
// 返回never的函数必须存在无法达到的终点
function error(message: string): never {
throw new Error(message);
}// 推断的返回值类型为never
function fail() {
return error('Something failed');
}
declare function create(o: object | null): void;
create({ prop: 0 });
// OK
create(function () {});
// OK
create([1]);
// OK
create(null);
// OK
// create(42);
// Error
// create('string');
// Error
// create(false);
// Error
// create(undefined);
// Error
function add(x: number, y: number): number {
return x + y;
}
const division = (x: number, y: number): number => {
return x / y;
};
// 书写完整函数类型
let myAdd: (baseValue: number, increment: number) => number = function (
x: number,
y: number,
): number {
return x + y;
};
const myDivision: (baseValue: number, increment: number) => number = (
x: number,
y: number,
): number => {
return x / y;
};
let age = 18;
// typescript会隐式类型推断其为number
let name = '18';
// typescript会隐式类型推断其为string
let className;
// typescript会隐式类型推断其为any
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;
interface LabelledValue {
label: string;
}function printLabel(labelledObj: LabelledValue) {
console.log(labelledObj.label);
}let myObj = { size: 10, label: 'Size 10 Object' };
printLabel(myObj);
interface SquareConfig {
color?: string;
width?: number;
}function createSquare(config: SquareConfig): { color: string;
area: number } {
let newSquare = { color: 'white', area: 100 };
if (config.color) {
newSquare.color = config.color;
}
if (config.width) {
newSquare.area = config.width * config.width;
}
return newSquare;
}let mySquare = createSquare({ color: 'black' });
console.log(mySquare);
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
// p1.x = 5;
// error!
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
getName(): string {
return this.name;
}
}
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
getName(): string {
return this.name;
}
}
console.log(new Person('zs').getName());
//zs
class Person {
private name: string;
constructor(name: string) {
this.name = name;
}
getName(): string {
return this.name;
}
}
new Person('zs').name;
// 错误: 'name' 是私有的.
class Person {
private name: string;
protected age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
class School extends Person {
constructor(name: string, age: number) {
super(name, age);
}
getName(): string {
return this.name;
// error,不能被访问
}
getAge(): number {
return this.age;
// OK,可以被访问
}
}
class Octopus {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor(theName: string) {
this.name = theName;
}
}
let dad = new Octopus('Man with the 8 strong legs');
dad.name = 'Man with the 3-piece suit';
// 错误! name 是只读的.
interface Run {
run(): void;
}
class Car implements Run {
run(): void {
console.log('我会跑...');
}
}
new Car().run();
abstract class Animal {
run(): void {
console.log('我会跑...');
}
}class Doc extends Animal {
eat(): void {
console.log('我会吃...');
}
}let doc = new Doc();
doc.eat();
doc.run();
// 普通函数
function createArray(...args: T[]): T[] {
return args;
}console.log(createArray(1, 2, 3));
console.log(createArray('jack', 'tom'));
// 箭头函数
const createArrayArrow = (...args: T[]): T[] => {
return args;
};
console.log(createArrayArrow(1, 2, 3));
console.log(createArrayArrow('jack', 'tom'));
import Vue from 'vue';
export default Vue.extend({
name: 'Button',
data() {
return {
count: 1,
};
},
methods: {
increment() {
this.count++;
},
},
});
装饰器是 ES 草案中的一个新特性,提供一种更好的面向切面编程的体验,不过这个草案最近有可能发生重大调整,所以个人并不推荐。装饰器函数接收的参数就是以前的组件选项对象(data、props、methods 之类)
import Vue from 'vue';
import Component from 'vue-class-component';
@Component({
props: {
size: String,
},
})
export default class Button extends Vue {
private count: number = 1;
private text: string = 'Click me';
get content() {
return `${this.text} ${this.count}`;
}increment() {
this.count++;
}mounted() {
console.log('button is mounted');
}
}
import { Vue, Component, Prop } from 'vue-property-decorator'@Component
export default class Button extends Vue {
private count: number = 1
private text: string = 'Click me'
@Prop() readonly size?: stringget content () {
return `${this.text} ${this.count}`
}increment () {
this.count++
}mounted () {
console.log('button is mounted')
}
}
import { AxiosInstance } from 'axios'declare module 'vue/types/vue' {
interface Vue {
readonly $api: AxiosInstance
}
}