// TS 开发准则: 只要是变量、或者对象属性,都应该有一个明确的类型
// 类型注解: 人工的告诉 TS,变量或者对象的明确属性类型
const userName: string = '123'
// 类型推断
const userAge = 18;
// 如果类型推断能够自动推断出来类型,就没必要去手写类型注解
let userNick = 'dell';
userNick.toLocaleUpperCase();
// 这种返回值就不用给,能够自动推断出两个number类型相加,返回的一定是number
function getTotal(paramOne: number, paramTwo: number) {
return paramOne + paramTwo;
}
getTotal(1,2);
// 如果类型推断推断不出来,或者推断的不准确,再去手写类型注解
const userInfo = {
name: ' dell'
age: 18
}
// typeof 类型收窄
function uppercase(content: string | number) {
if(typeof content === 'string'){
return content.toUpperCase();
}
return content;
}
// 真值收窄
function getString(content?: string) {
if(content) {
return content.toUpperCase();
}
}
// 相等收窄
function example(x: string | number, y: string | boolean) {
if(x === y) {
return x.toUpperCase();
}
}
// 对象类型解构的代码怎么写
function getOjbectValue({a, b}: {a: string, b: string}){
return a + b;
}
getOjbectValue({a:'1',b: '2'});
// 变量类型以定义变量时的类型为准
let userName = '123'; // 这里就会自动判断类型为string,后面使用这个变量必须传string类型,否则会报错
userName = '123';
type Fish = { swim: () => {} }
type Bird = { fly: () => {} }
// In 语法下的类型收窄
function test(animal: Fish | Bird) {
if('swim' in animal) {
return animal.swim();
}
return animal.fly();
}
// Instanceof 语法下的类型收窄
function test1(param: Date | string) {
if(param instanceof Date) {
return param.getTime();
}
return param.toUpperCase();
}
// animal is Fish 叫做类型陈述语法
function isFish(animal: Fish | Bird): animal is Fish {
if((animal as Fish).swim !== undefined) {
return true
}
return false;
}
function test2(animal: Fish | Bird) {
if(isFish(animal)) {
return animal.swim();
}
return animal.fly();
}
// 有属性的函数类型定义方法
interface FunctionWithAttributes {
attr: string;
(str: string): void;
}
const test: FunctionwithAttributes = (str: string) => {
console.log(str);
}
test.attr = 'attributes';
// 构造函数的类型如何定义
interface ClasswithConstructor {
new (str: string): void;
}
function testOne(outerClass: ClassWithConstructor) {
const instance = new outerClass( 'new' )
}
class TestOne {
name: string;
constructor(str: string) {
this.name = str;
}
}
testOne(TestOne);
// 如何写 Date 的类型
interface DateTpye {
new (): Date; // 如果是一个Date类型
(dateString: string): string; // 如果是一个函数,就返回一个string类型
}
// 函数和泛型
function getArrayFirstItem<Type>(arr: Type[]): Type{ // type泛型,根据数组里面的内容会自行判断是什么类型
return arr[0];
}
const numberArr = [1,2,3];
const result = getArrayFirstItem(numberArr);
const stringArr = ['1', '2','3'];
const resultOne = getArrayFirstItem(stringArr);
// 函数重载
function getString(str: string): string; // 重载函数的定义
function getString(str: string, str1: string): number; // 重载函数的定义
function getString(str: string,str1?: string) { // 重载函数的实现
if(typeof str1 === 'string') {
return (str + str1).length;
}
return str;
}
function showPerson({name: nick = 'dell', age: old = 30}) { // 将name和age解构通过nick和old打印出来
console.Log(nick);
console.log(old);
}
// 对象类型和对象解构语法要分清
function showPerson({name = 'dell', age = 30}: {name: string, age: number}) {
console.log(name);
console.Log(age);
}
// interface 中的 readonly 只读属性
interface Person {
readonly name: string;
age: number;
}
const dell: Person = {name: 'dell', age: 30};
dell.name = 'wayne'; // 会报错,因为name只允许读,不允许修改
dell.age = 30;
//如何给对象扩展属性
interface ArrayObject {
[key: string]: string | number | boolean; // 表示可以往里面添加内容,但是键必须是字符串类型
length: number;
}
const obj: ArrayObject = {
ad: '123',
test: true,
length: 0
}
// 对象类型的继承
interface Animal {
name: string;
age: number;
breath: () => void;
}
interface Dog extends Animal {
bark: () => void;
}
const animal: Animal = {
name: ' panda'
age: 1,
breath: () => {}
}
const dog: Dog = {
name: 'panda'
age: 1,
breath:() =>{},
bark: () =>{}
}
// 多个对象类型同时进行集成
interface Circle {
radius: number;
}
interface Colorful {
color: string;
}
interface ColorfulCircle extends Circle, Colorful {}
const colorfulCircle: ColorfulCircle = {
radius: 1,
color: 'red'
}
// 交叉类型
type ColorfulCircleOne = Circle & Colorful;
const colorfulCircleOne: ColorfulCircleOne = {
radius: 1,
color: 'red'
}
// 泛型 type就是泛型,可以理解为泛型就是一个你所要使用时传的一个值,例如string、number、boolean等等
interface Box<Type> {
content: Type
}
const box: Box<string> = {
content: 'box'
}
const box1: Box<number> = {
content: 123
}
const box2: Box<boolean> = {
content: true
}
// 使用泛型来扩展生成新的类型
type TypeOrNull<Type> = Type null;
type OneOrMany<Type> = Type Type[];
// type OneOrManyrNull<Type> = OneOrMany<Type> null;
type One0rMany0rNull<Type> = TypeOrNull<One0rMany<Type>>;
// 数组和泛型
interface SelfArray<Type> {
[key: number]: Type;
length: number;
pop(): Type | undefined;
push(...items: Type[]): number;
}
const numberArr: SelfArray<string> = ['1','2','3'];
// 数组的 Readonly 修饰符
function doStuff(arr: readonly string[]){
arr.push('123'); // 会报错,因为只读,push是会修改数组,所以会报错
}
// 元组
type Point = [number, number];
function getPoint([x,y]: Point) {
return x + y;
}
const point: Point = [1, 2];
getPoint(point);
// 元组 Readonly
type Point = readonly [number, number,string];
function getPoint([x,y,z]: Point) {
return x + y + z;
}
const point: Point = [1, 2,'string'];
point[0] = 3; // 会报错,只允许读,不允许修改
getPoint(point);
// extends 和泛型的结合,解决固定参数传递需求
interface Person {
name: string;
}
function getName<Type extends Person>(person: Type) {
return person.name;
}
getName({name: 'dell', age: 30, gender: '123123'}); // 配合泛型使用,传入person里面没有的属性也不会报错,但是name就是必填项
// keyof 指的是对象类型中的某一项
interface Teacher {
name: string;
age: number;
sex: 'male'| 'female';
}
const teacher:Teacher = {
name: 'Dell'
age: 30,
sex: 'male'
}
function getTeacherInfo<T extends keyof Teacher>(teacher: Teacher, key: T){
return teacher[key];
}
getTeacherInfo(teacher, 'name');
// 条件类型: 是根据条件,生成一个新的类型
interface Animal {
breath: () => {}
}
interface Dog extends Animal {
bark: () => {}
}
interface Tank {
pH: number
}
type Example = Tank extends Animal ? string : number; // tank是否继承了animal,如果继承了则给example负值string
// 使用条件类型的例子,可以让我们的函数重载的语法更简练
Iinterface IdLabel {
id: number;
}
interface NameLabel {
name: string;
}
type IdOrNameLabel<T> = T extends number ? IdLabel : NameLabel;
function createlabel<T extends string | number>(key: T): IdOrNameLabel<T>;
function createLabel(key: string number): IdLabel | NameLabel {
if(typeof key === 'string') {
return { name: key }
}
return { id: key }
}
const label = createLabel('dell');
const label1 = createLabel(123);
// 条件类型其他的应用场景
type Type0fMessages<T> = T extends { message unknown} ? T['message']: never;
interface Email {
from: string,
to: string;
message: string;
}
const emailObject: Email = [
from: 'dell@qq.com',
to: 'leeagg.com'
message: 'hello lee'
}
const email: Type0fMessage<Email> = 'hello lee';
// 条件类型其他使用场景
type GetRetureType<T> = T extends (...args: never[]) => infer RetureType ? RetureType : never;
type example = GetRetureType<() => string>;
type example1 = GetRetureType<string>;
// 条件类型其他使用场景
type ToArray<T> = [T] extends [any] ? T[]: never; // 这样就可以让数组里面既可以是string类型也可以是number类型
type StringOrNumberArray = ToArray<string | number>;
type NeverType = ToArray<never>;
// 基础映射类型
// 将只读属性readonly关键字删掉,使用-readonly
interface User {
readonly name: string;
readonly age: number;
male?: boolean;
}
type FilterReadOnly<Type> = { // -readonly将只读关键字删掉,-?,将非必填改成必填
- readonly [Property in keyof Type] - ? : Type[Property];
}
type PublicUser = FilterReadOnly<User>;
const publicUser: PublicUser = {
name: ' dell',
age: 30,
male: true,
}
publicUser.age = 31;
// 映射类型高级语法
// 1. exclude 将某个字段从中删除
interface User {
name: string;
age: number;
male: boolean;
}
type DeleteMaleProperty<Type> = {
[Property in keyof Type as Exclude<Property, 'male'>]: Type[Property];
}
type UserWithoutGender = DeleteMaleProperty<User>;
const user: UserwithoutGender = {
fname: ' dell'
age: 30,
}
// 2。字面量语法例子
interface User { // 转化前的
name: string;
age: number;
male: boolean;
}
interface UserFunctions { // 想转化成的
getName: ()=> string;
getAge: ()=>number;
getMale: ()=> boolean;
}
type GetPropertyFunctions<Type> = {
[Property in keyof Type as 'get$(Capitalize<string & Property>)']: () => Type[Property];
}
type UserFunctionsType = GetPropertyFunctions<User>;
// 3.union 类型使用
type SquareEvent = {
kind: 'square';
x: number;
y: number;
}
type CircleEvent = {
kind:'circle';
radius: number;
}
type GenerateEventsFunctions<Events extends { kind: string }> = {
[Event in Events as Event[' kind']]: (event: Event) => number;
}
type NewType = GenerateEventsFunctions<SquareEvent | CircleEvent>
// 类
class Person {
name = ' dell';
getName() {
return this.name;
}
}
class Teacher extends Person { // 类的继承
fgetTeacherName() {
return 'Teacher';
}
getName(){
return super.getName() + 'lee'; // 通过super调用父类的方法
}
}
const teacher = new Teacher();
// private,protected,public 访问类型
// public 允许我在类的内外被调用
// tprivate 允许在类内被使用
// protected 允许在类内及继承的子类中使用
class Person {
protected name: string;
public sayHi(){
this.name;
console.log('hi');
}
}
class Teacher extends Person {
public sayBye() {
this.name;
}
}
// constructor 构造器
class Person {
// 传统写法
// public name: string;
// constructor(name: string) {
// this.name = name!
// }
// 简化写法
constructor(public name: string) {}
}
const person = new Person('dell') // 会将这个dell直接赋值给 constructor
// 子类也有构造器 子类如果使用构造器,一定得用super调用父类的构造器
class Person {
constructor(public name: string) {}
}
class Teacher extends Person {
constructor(public age: number) {
super('dell'); // 这个super是指必须给父类的构造器传参,否则会报错
}
}
const teacher = new Teacher(28)
class Person {
constructor(private _name: string) {}
get name() {
return this._name + ' lee';
}
set name(name: string) {
const realName = name.split( ')[0]
this._name = realName
}
}
const person = new Person('dell')
class Demo {
private static instance: Demo;
private constructor(public name: string) {}
static getInstance() {
if (!this.instance) {
this.instance = new Demo('dell lee');
return this.instance;
}
}
const demo1 = Demo.getInstance();
const demo2 = Demo.getInstance();
// 抽象类 使用abstract关键字,抽象类只能被继承,不能实例化
abstract class Geom {
width: number;
getType() {
return 'Gemo';
}
abstract getArea(): number;
}
class Circle extends Geom {
getArea() { // 抽象方法也得自己在子类实现,否则会报错
return 123;
}
}
typescript使用笔记二
于 2022-12-24 20:51:41 首次发布