什么是TS
TypeScript是JavaScript的超集,意味着它能做JavaScript所做的一切,但有一些附加功能。
why?
- JS是一门动态类型的预言,这意味着变量可以改变类型
- TS为JS添加静态类型,这意味着变量类型在程序的任何时候都不能被改变
注: TS不被浏览器理解,所以TS => (TSC编译器)编译 => JS
优点
- 帮助发现错误
- 更可读,帮助了解其他开发人员的意图
- 受欢迎
- 更好理解JS
缺点
- 更长的编写时间(小项目不值得使用)
- 必须编译(在大项目中更花时间)
花更多时间,编写更精确的代码然后编译,来减少代码错误
使用
// 安装
npm i -g typescript
// 检查
tsc -v
// index.ts
let sport = 'football';
let id = 5;
// 编译
tsc index
// 编译重命名
tsc index.ts --outfile file-name.js
// 监听改动自动编译
tsc index.ts -w
// 配置tsconfig.json
tsc --init
TS会编译代码,无论是否有错误,他家顶开发者知道的更多。
类型
原始类型
- string
- number
- bigint
- boolean
- undefined
- null
- symbol
Primitives is immutable(原始值不可变)
let name = 'Danny';
name.toLowerCase();
console.log(name); // 字符串方法不改变字符串值
let arr = [1, 3, 5, 7];
arr.pop();
console.log(arr); // 数组方法改变数组值
name = 'Anna' // 赋新值,而非改变原值
包装对象
let firstname = new String('Danny');
console.log(firstname); // String {'Danny'}
除null和undefined,原始值均有对应的对象--包裹着原始值:String、Number、BigInt、Boolean和Symbol。
包装对象提供了允许原始值被操纵的方法。
:type
类型注解
let id: number = 5;
let firstname: string = 'danny';
let hasDog: boolean = true;
let unit: number; // Declare variable without assigning a value
unit = 5;
一般不必使用类型注解,TS可自动推断
let id = 5; // TS knows it's a number
let firstname = 'danny'; // TS knows it's a string
let hasDog = true; // TS knows it's a boolean
hasDog = 'yes'; // ERROR
联合类型
let age: string | number;
age = 26;
age = '26';
引用类型
- 数组
- 对象
- 函数
原始类型与引用类型
- 每个原始值都存储在内存中的一个唯一位置。
let x = 2;
let y = 1;
x = y;
y = 100;
console.log(x); // 1 (even though y changed to 100, x is still 1)
- 引用类型指向的是存储对象的一个内存位置
let point1 = { x: 1, y: 1 };
let point2 = point1;
point1.y = 100;
console.log(point2.y); // 100 (point1和point2多指向的是存储点对象的同一个内存地址)
TS数组
let ids: number[] = [1, 2, 3, 4, 5]; // can only contain numbers
let names: string[] = ['Danny', 'Anna', 'Bazza']; // can only contain strings
let options: boolean[] = [true, false, false]; can only contain true or false
let books: object[] = [
{ name: 'Fooled by randomness', author: 'Nassim Taleb' },
{ name: 'Sapiens', author: 'Yuval Noah Harari' },
]; // can only contain objects
let arr: any[] = ['hello', 1, true]; // any basically reverts TypeScript back into JavaScript
ids.push(6);
ids.push('7'); // ERROR: Argument of type 'string' is not assignable to parameter of type 'number'.
let person: (string | number | boolean)[] = ['Danny', 1, true];
person[0] = 100;
person[1] = {name: 'Danny'} // Error - person array can't contain objects
元组
元组是一个具有固定大小和已知数据类型的数组
let person: [string, number, boolean] = ['Danny', 1, true];
person[0] = 100; // Error - Value at index 0 can only be a string
TS对象
// Declare a variable called person with a specific object type annotation
let person: {
name: string;
location: string;
isProgrammer: boolean;
};
// Assign person to an object with all the necessary properties and value types
person = {
name: 'Danny',
location: 'UK',
isProgrammer: true,
};
person.isProgrammer = 'Yes'; // ERROR: should be a boolean
person = {
name: 'John',
location: 'US',
};
// ERROR: missing the isProgrammer property
interface(接口)
通常使用接口检查对象属性,特别是多个对象是否具有相同的特定属性和价值类型
interface Person {
name: string;
location: string;
isProgrammer: boolean;
}
let person1: Person = {
name: 'Danny',
location: 'UK',
isProgrammer: true,
};
let person2: Person = {
name: 'Sarah',
location: 'Germany',
isProgrammer: false,
};
函数属性
interface Speech {
sayHi(name: string): string; // JS func
sayBye: (name: string) => string; // ES6箭头函数
}
let sayStuff: Speech = {
sayHi: function (name: string) {
return `Hi ${name}`;
},
sayBye: (name: string) => `Bye ${name}`,
};
console.log(sayStuff.sayHi('Heisenberg')); // Hi Heisenberg
console.log(sayStuff.sayBye('Heisenberg')); // Bye Heisenberg
ts并不关心箭头函数还是普通函数。
TS函数
// Define a function called circle that takes a diam variable of type number, and returns a string
function circle(diam: number): string {
return 'The circumference is ' + Math.PI * diam;
}
console.log(circle(10)); // The circumference is 31.41592653589793
const circle = (diam: number): string => {
return 'The circumference is ' + Math.PI * diam;
};
console.log(circle(10)); // The circumference is 31.41592653589793
?:
可选参数
// c是联合类型,也时刻u西安参数
const add = (a: number, b: number, c?: number | string) => {
console.log(c);
return a + b;
};
console.log(add(5, 4, 'I could pass a number, string, or nothing here!'));
// I could pass a number, string, or nothing here!
// 9
:void
只声明,不返回
// Declare the varible sayHello, and give it a function signature that takes a string and returns nothing.
let sayHello: (name: string) => void;
// Define the function, satisfying its signature
sayHello = (name) => {
console.log('Hello ' + name);
};
sayHello('Danny'); // Hello Danny
any
动态类型
将TypeScript还原成JavaScript:
let age: any = '100';
age = 100;
age = {
years: 100,
months: 2,
};
类型别名
type StringOrNumber = string | number;
type PersonObject = {
name: string;
id: StringOrNumber;
};
const person1: PersonObject = {
name: 'John',
id: 1,
};
const person2: PersonObject = {
name: 'Delia',
id: 2,
};
const sayHello = (person: PersonObject) => {
return 'Hi ' + person.name;
};
const sayGoodbye = (person: PersonObject) => {
return 'Seeya ' + person.name;
};
TSDOM
TS不能访问DOM,因此不能确定DOM元素是否真的存在。
const link = document.querySelector('a');
console.log(link.href); // ERROR: Object is possibly 'null'. TypeScript can't be sure the anchor tag exists, as it can't access the DOM
!
非空断言操作符
// 在这里,我们告诉TypeScript,我们确定这个锚点标签存在
const link = document.querySelector('a')!;
console.log(link.href); // www.freeCodeCamp.org
TS可以自动推理出HTMLAnchorElement
类型
类型转换
const form = document.getElementById('signup-form');
console.log(form.method);
// ERROR: Object is possibly 'null'.
// ERROR: Property 'method' does not exist on type 'HTMLElement'.
const form = document.getElementById('signup-form') as HTMLFormElement;
console.log(form.method); // post
event
TS内置的事件对象
const form = document.getElementById('signup-form') as HTMLFormElement;
form.addEventListener('submit', (e: Event) => {
e.preventDefault(); // prevents the page from refreshing
console.log(e.tarrget); // ERROR: Property 'tarrget' does not exist on type 'Event'. Did you mean 'target'?
});