import { CodeSurferLayout } from 'code-surfer'; import { Appear } from 'mdx-deck'; export { nightOwlFull as theme } from 'code-surfer/themes';
TypeScript 是什么?
npx ts-lib-scripts create ts-hello-world
let isDone: boolean = fasle;
isDone = 2; // Error,不能将类型"2"分配给类型“boolean”
const decLiteral: number = 6;
const hexLiteral: number = 0xf00d;
const binaryLiteral: number = 0b1010;
const octalLiteral: number = 0o744;
let name: string = 'bob';
name = 'smith';
let list: number[] = [1, 2, 3];
let list: Array<number> = [1, 2, 3];
// 定义元祖类型
let x: [string, number];
// 初始化
x = ['hello', 10]; // OK
x = [10, 'hello']; // 错误,类型不匹配
let x: [string, number];
x = ['hello', 10]; // OK
x = [10, 'hello']; // 错误,类型不匹配
console.log(x[0].substr(1));
let x: [string, number];
x = ['hello', 10]; // OK
x = [10, 'hello']; // 错误,类型不匹配
console.log(x[0].substr(1));
let x: [string, number];
x = ['hello', 10]; // OK
x = [10, 'hello']; // 错误,类型不匹配
console.log(x[0].substr(1));
console.log(x[1].substr(1));
let x: [string, number];
x = ['hello', 10]; // OK
x = [10, 'hello']; // 错误,类型不匹配
console.log(x[0].substr(1));
console.log(x[1].substr(1));
let notSure: any = 4;
notSure = 'maybe a string instead';
notSure = false;
function fn(): void {
console.log('这是一个函数类型声明');
}
let u: undefined = undefined;
let n: null = null;
enum Color {
Red,
Green,
Blue,
}
const c: Color = Color.Green;
enum Color {
Red = 1,
Green,
Blue,
}
const c: Color = Color.Green;
enum Color {
Red = 1,
Green = 2,
Blue = 4,
}
const c: Color = Color.Green;
enum Color {
Red = 1,
Green,
Blue,
}
let colorName: string = Color[2];
console.log(colorName);
enum Color {
Red = 1,
Green,
Blue,
}
let colorName: string = Color[2];
console.log(colorName);
declare function create(o: object | null): void;
create({ prop: 0 }); // OK
create(null); // OK
create(42); // Error
create('string'); // Error
create(false); // Error
create(undefined); // Error
const someValue: any = 'this is a string';
const strLength: number = (<string>someValue).length;
const someValue: any = 'this is a string';
const strLength: number = (someValue as string).length;
以上两种类型断言的形式是等价的,至于用哪个,大部分时候看个人喜好。
但是,当在 TypeScript 里使用到 JSX 时,必须使用 as 语法形式的断言。
ts 非空断言关键字(!)
!和?是相对的,表示强制解析(也就是告诉 typescript 编译器,这里一定有值)
const element = document.querySelector('.item');
console.log(element.getBoundingClientRect());
console.log(element!.getBoundingClientRect());
const element = document.querySelector('.item');
console.log(element.getBoundingClientRect());
console.log(element!.getBoundingClientRect());
interface Props {
userName: string;
}
function Hello(props: Props) {
return <div>Hello, {props.userName}</div>;
}
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' });
interface Point {
readonly x: number;
readonly y: number;
}
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!
let p1: Point = { x: 10, y: 20 };
p1.x = 5; // error!
function add(x, y) {
return x + y;
}
function add(x, y) {
return x + y;
}
function add(x: number, y: number): number {
return x + y;
}
function add(x: number, y: number): number {
return x + y;
}
add(1, 2); // OK
add(1, '2'); // error
add(1, 2); // OK
add(1, '2'); // error
函数作为值传递时的类型声明。
function calc(
x: number,
y: number,
calcFn: ???,
): number {
return calcFn(x, y);
}
function calc(
x: number,
y: number,
calcFn: ???,
): number {
return calcFn(x, y);
}
function calc(
x: number,
y: number,
calcFn: (x: number, y: number) => number,
): number {
return calcFn(x, y);
}
function add(x: number, y: number): number {
return x + y;
}
calc(1, 2, add); // ok
function pow(x: number, y: number): number {
return x ** y;
}
calc(1, 2, pow); // ok
function divide(x: number, y: number): number {
return x / y;
}
calc(2, 1, divide); // ok
function sum(x: number, y: number, z: number): number {
return x + y + z;
}
calc(1, 2, sum); // error
interface Point {
readonly x: number;
readonly y: number;
distinct(anotherPoint: Point): number;
}
interface Point {
readonly x: number;
readonly y: number;
distinct(anotherPoint: Point): number;
}
interface Point {
readonly x: number;
readonly y: number;
distinct: (anotherPoint: Point) => number;
}
function buildName(firstName: string, lastName?: string) {
return firstName + lastName;
}
function buildName(firstName: string, lastName?: string) {
return firstName + lastName;
}
buildName('Bob'); // ok
buildName('Bob', 'Alias'); // ok
buildName('Bob', 'Alias', 'Axx'); // error
function buildName(firstName?: string, lastName: string) {
return firstName + lastName;
}
function buildName(firstName?: string, lastName: string) {
return firstName + lastName;
}
function buildName(firstName: string | undefined, lastName: string) {
return firstName + lastName;
}
function buildName(firstName?: string, lastName?: string) {
return firstName + lastName;
}
function buildName(
firstName: string | undefined,
lastName: string | undefined,
) {
return firstName + lastName;
}
可以为可选参数添加上默认值。这样,调用函数时,如果该函数参数为undefined
,则该参数为默认值。
function buildName(firstName: string, lastName: string = 'Smith') {
return firstName + lastName;
}
const result1 = buildName('Bob'); // OK, result1 = Bob Smith
const result2 = buildName('Bob', 'Adams'); // OK, result2 = Bob Adams
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number) {
alert(this.name + 'moved' + distanceInMeters + 'm');
}
}
const animal = new Animal('Kiki');
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number) {
alert(this.name + 'moved' + distanceInMeters + 'm');
}
}
const animal = new Animal('Kiki');
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number) {
alert(this.name + 'moved' + distanceInMeters + 'm');
}
}
const animal = new Animal('Kiki');
class Animal {
name: string;
constructor(theName: string) {
this.name = theName;
}
move(distanceInMeters: number) {
alert(this.name + 'moved' + distanceInMeters + 'm');
}
}
const animal = new Animal('Kiki');
class Animal {
public name: string;
public constructor(theName: string) {
this.name = theName;
}
public move(distanceInMeters: number) {
alert(this.name + 'moved' + distanceInMeters + 'm');
}
}
class Animal {
private name: string;
constructor(theName: string) {
this.name = theName;
}
}
new Animal('Cat').name; // 错误: 'name' 是私有的.
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return (
'Hello, my name is' + this.name + 'and I work in' + this.department + '.'
);
}
}
let howard = new Employee('Howard', 'Sales');
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return (
'Hello, my name is' + this.name + 'and I work in' + this.department + '.'
);
}
}
let howard = new Employee('Howard', 'Sales');
console.log(howard.getElevatorPitch());
console.log(howard.name); // 错误我们不能在 Person类外使用 name
class Person {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return (
'Hello, my name is' + this.name + 'and I work in' + this.department + '.'
);
}
}
let howard = new Employee('Howard', 'Sales');
console.log(howard.getElevatorPitch());
class Person {
protected name: string;
protected constructor(theName: string) {
this.name = theName;
}
}
// Employee 能够继承 Person
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return (
'Hello, my name is' + this.name + 'and I work in' + this.department + '.'
);
}
}
let howard = new Employee('Howard', 'Sales');
let john = new Person('John'); // 错误: 'Person' 的构造函数是被保护的.
类型推论
对于能够显而易见的推断出变量类型的,TypeScript 允许我们省略类型声明,这就是类型推论
let x: number = 0;
x = 1; // OK
x = '1'; // error
let x = 0;
x = 1; // OK
x = '1'; // error
const x = [0, 1, null];
const zoo = [new Rhino(), new Elephant(), new Snake()];
<button
onClick={(event) => {
console.log(event);
}}
>
点击我
</button>;
const x = [0, 1, null];
const zoo = [new Rhino(), new Elephant(), new Snake()];
<button
onClick={(event) => {
console.log(event);
}}
>
点击我
</button>;
const x = [0, 1, null];
const zoo = [new Rhino(), new Elephant(), new Snake()];
<button
onClick={(event) => {
console.log(event);
}}
>
点击我
</button>;
const x = [0, 1, null];
const zoo = [new Rhino(), new Elephant(), new Snake()];
<button
onClick={(event) => {
console.log(event);
}}
>
点击我
</button>;
类型参数化。
const items: Array<number> = [1, 2, 3];
const names: Array<string> = ['张三', '李四', '王五'];
const items: Array<number> = [1, 2, 3];
const names: Array<string> = ['张三', '李四', '王五'];
const items: Array<number> = [1, 2, 3];
const names: Array<string> = ['张三', '李四', '王五'];
const items: Array<number> = [1, 2, 3];
const names: Array<string> = ['张三', '李四', '王五'];
const items: Array<number> = [1, 2, 3];
const names: Array<string> = ['张三', '李四', '王五'];
function createArray(length: number, value: any): any[] {
return new Array(length).fill(value);
}
function createArray(length: number, value: any): any[] {
return new Array(length).fill(value);
}
function createArray(length: number, value: string): string[] {
return new Array(length).fill(value);
}
function createArray(length: number, value: boolean): boolean[] {
return new Array(length).fill(value);
}
function createArray(length: number, value: Date): Date[] {
return new Array(length).fill(value);
}
function createArray(length: number, value: T): T[] {
return new Array(length).fill(value);
}
function createArray(length: number, value: T): T[] {
return new Array(length).fill(value);
}
function createArray<T>(length: number, value: T): T[] {
return new Array(length).fill(value);
}
function createArray<T>(length: number, value: T): T[] {
return new Array(length).fill(value);
}
调用泛型函数,需要给类型变量赋“值”
这个“值”指类型,而非像1, '2', true这样的真实值
const items = createArray<number>(3, 1);
const strs = createArray<string>(3, '');
const items = createArray<number>(3, 1);
const strs = createArray<string>(3, '');
const items = createArray<number>(3, 1);
const strs = createArray<string>(3, '');
const items = createArray<number>(3, 1);
const strs = createArray<string>(3, '');
const items = createArray<number>(3, 1);
const strs = createArray<string>(3, '');
const items = createArray<number>(3, 1);
const strs = createArray<string>(3, '');
const items = createArray(3, 1);
const strs = createArray<string>(3, '');
const items = createArray(3, 1);
const strs = createArray<string>(3, '');
const items = createArray(3, 1);
const strs = createArray(3, '');
interface List<T> {
length: number;
items: T[];
get(index: number): T;
}
const items: List<number> = {
length: 3,
items: [1, 2, 3],
get(index: number) {
return this.items[index];
},
};
class List<T> {
public items: T[];
public constructor(items: T[]) {
this.items = items;
}
public get length() {
return this.items.length;
}
public getItem(index: number): T {
return this.items[index];
}
}
const items = new List<number>([1, 2, 3]);
class List<T> {
public items: T[];
public constructor(items: T[]) {
this.items = items;
}
public get length() {
return this.items.length;
}
public getItem(index: number): T {
return this.items[index];
}
}
const items = new List<number>([1, 2, 3]);
class List<T> {
public items: T[];
public constructor(items: T[]) {
this.items = items;
}
public get length() {
return this.items.length;
}
public getItem(index: number): T {
return this.items[index];
}
}
const items = new List<number>([1, 2, 3]);
class List<T> {
public items: T[];
public constructor(items: T[]) {
this.items = items;
}
public get length() {
return this.items.length;
}
public getItem(index: number): T {
return this.items[index];
}
}
const items = new List([1, 2, 3]);
规定泛型必须遵循的规则。
使用extends关键字添加泛型约束。
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // ok
return arg;
}
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // ok
return arg;
}
interface Lengthwise {
length: number;
}
function loggingIdentity<T extends Lengthwise>(arg: T): T {
console.log(arg.length); // ok
return arg;
}
loggingIdentity(3); // error
loggingIdentity({ length: 10, value: 3 }); // OK
通过<T = 默认类型>
为泛型指定默认的类型
function getItemElements<T extends Element = HTMLDivElement>(): NodeListOf<T> {
return document.querySelectorAll<T>('.item');
}
type AnotherTypeName = string | number | null
T0 = T1 & T2 ===> T0既是T1又是T2
T0 = T1 & T2 ===> T0包含所有T1和T2定义的属性
// 二维点
interface Point {
readonly x: number;
readonly y: number;
}
// 第三维度坐标
interface ZCoordinate {
readonly z: number;
}
// 三维点
type ThreeDimensionalPoint = Point & ZCoordinate;
/*
ThreeDimensionalPoint相当于:
{
readonly x: number;
readonly y: number;
readonly z: number;
}
*/
T0 = T1 | T2 | T3 ===> T0只能是T1、T2、T3三者之一
let item: string | number | undefined;
item = '1'; // OK
item = undefined; // OK
item = 1; // OK
item = false; // error
item = null; // error
谢谢!!!!
👏👏👏
🎉🎉🎉