// 构造类型 T ,并将它所有的属性设置为可选的。
// 返回值表示输入类型的所有子类型。
// Partial<T>
// interface Todo {
// title: string;
// description: string;
// }
// function updateTodo(todo: Todo, fieldsToUpdate: Partial<Todo>) {
// return { ...todo, ...fieldsToUpdate };
// }
// const todo1 = {
// title: 'hahhah',
// description: 'hahhahahahhahahah'
// }
// const todo2 = updateTodo(todo1, { description: '啊啊啊啊啊啊啊' });
// Readonly<T>
// 构造类型 T ,并将它所有的属性设置为 readonly,也就是说构造出来的类型的属性不能再次被赋值。
// interface Todo {
// title: string;
// }
// const todo: Readonly<Todo> = {
// title: 'Delete inactive users',
// };
// todo.title = 'Hello'; // Error: cannot reassign a readonly property
// 这个工具可用来表示在运行时会失败的赋值表达式(比如:当尝试给冻结对象的属性再次赋值时)
// Object.freeze
// function freeze<T>(obj: T): Readonly<T>;
// Record<K,T>
// 构造一个类型,其属性值的类型为 T 。这个工具可用来将某个类型的属性映射到另一个类型上。
// interface PageInfo {
// title: string;
// }
// type Page = 'home' | 'about' | 'cantact';
// const x: Record<Page, PageInfo> = {
// about: { title: 'about' },
// cantact: { title: "cantact" },
// home: { title: 'home' }
// }
// Pick<T,K>
// 从类型 T 中挑选部分属性 K 来构造类型
// interface Todo {
// title: string;
// description: string;
// completed: boolean;
// }
// type TodoPreview = Pick<Todo, 'title' | 'completed'>;
// const todo: TodoPreview = {
// title: 'hahhahahhaha',
// completed: false
// }
// Omit<T,K>
// 从类型 T 中获取所有属性,然后从中剔除 K 属性后构造一个类型。
// interface Todo {
// title: string;
// description: string;
// completed: boolean;
// }
// type TodoPreview = Omit<Todo, 'description'>;
// const todo: TodoPreview = {
// title: 'Clean room',
// completed: false,
// };
// Exclude<T,U>
// 从类型 T 中剔除所有可以赋值给 U 的属性,然后构造一个类型。
// type T0 = Exclude<'a' | 'b' | 'c', 'a'>;
// type T1 = Exclude<'a' | 'b' | 'c', 'a' | 'b'>;
// type T2 = Exclude<string | number | (() => void), Function>;
// Extract<T,U>
// 从类型 T 中提取所有可以赋值给 u 的类型,然后构造一个类型。
// type T0 = Extract<'a' | 'b' | 'c', 'a' | 'f'>;
// type T1 = Extract<string | number | (() => void), Function>;
// NonNullabel<T>
// 从类型 T 中剔除 null 和 undefined ,然后构造一个类型。
// type T0 = NonNullable<string | number | undefined>;
// type T1 = NonNullable<string[] | null | undefined>;
// ReturnType<T>
// 由函数类型 T 的返回值类型构造出一个类型
// type T0 = ReturnType<() => string>;
// type T1 = ReturnType<(s: string) => void>;
// type T2 = ReturnType<(<T>() => T)>;
// type T3 = ReturnType<(<T extends U, U extends number[]> () => T)>;
// type T4 = ReturnType<typeof f1>; // { a: number, b: string }
// type T5 = ReturnType<any>;
// type T6 = ReturnType<never>;
// type T7 = ReturnType<string>;
// type T8 = ReturnType<Function>;
// InstanceType<T>
// 由构造函数类型 T 的实例类型构造一个类型。
// class C {
// x = 0;
// y = 1;
// }
// type T0 = InstanceType<typeof C>;
// type T1 = InstanceType<any>;
// type T2 = InstanceType<never>;
// type T3 = InstanceType<string>;
// type T4 = InstanceType<Function>;
// Required<T>
// 构造一个类型,使类型 T 的所有属性为 required
// interface Props {
// a?: number;
// b?: string;
// }
// const obj: Props = { a: 5 };
// const obj2: Required<Props> = { a: 5 };
// ThisType<T>
// 这个工具不会返回一个转换后的类型。它做为上下文的 this 类型的一个标记。注意,若想使用此类型
// ,必须启用 --noImplicitThis
type ObjectDescriptor<D, M> = {
data?: D;
methods?: M & ThisType<D & M>;
}
function makeObject<D, M>(desc: ObjectDescriptor<D, M>): D & M {
let data: object = desc.data || {};
let methods: object = desc.methods || {};
return { ...data, ...methods } as D & M;
}
let obj = makeObject({
data: { x: 0, y: 0 },
methods: {
moveBy(dy: number, dy: number) {
this.x += dx;
this.y += dy;
}
}
})
obj.x = 10;
obj.y = 20;
obj.moveBy(5, 5);
// interface Person {
// firstName: string;
// lastName: string;
// }
// function greeter(person: Person) {
// return "Hello, " + person.firstName + " " + person.lastName;
// }
// let user = { firstName: "Jane", lastName: "User" };
// document.body.textContent = greeter(user);
// function aa(obj: { label: string }) {
// console.log(obj.label)
// }
// let myobj = { size: "10", label: '少时诵诗书' };
// aa(myobj);
// interface Point {
// readonly x: number;
// readonly y: number;
// }
// let p1: Point = { x: 10, y: 20 };
// // p1.x = 5;
// TypeScript具有 ReadonlyArray<T> 类型,它与 Array<T> 相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改:
// let a: number[] = [1, 2, 3, 4, 5];
// let ro: ReadonlyArray<number> = a;
// // ro[0] = 12;
// // ro.push(5);
// // ro.length = 100;
// // a = ro;
// 可以看到,就算把整个 ReadonlyArray 赋值到一个普通数组也是不可以的。但是你可以用类型断言重写:
// a = ro as number[];
// readonly vs const
// 做为变量使用用 const ,若作为属性使用 readonly
// function identity(arg: number): number {
// return arg;
// }
// function identity(arg: any): any {
// return arg;
// }
function identity<T>(arg: T): T {
return arg;
}
let output = identity<string>('myString');
let output_ = identity('myString');
// 我们给 identity 添加了类型变量 T, T 帮助我们捕获用户传入的类型(比如:number),之后我们就可以使用这个类型。之后我们再次使用了 T 当作返回值类型。现在可以知道参数类型与返回值类型是相同的了。这允许我们跟踪函数里使用的类型的信息。
// 我们把这个版本的 identity 函数叫做泛型,因为它适用于多个类型。不同于使用 any ,它不会丢失信息,保持准确性,
// 定义了泛型函数后,可以用两种方法使用,第一种是,传入所有的参数,包含类型参数:
// 第二种方法更普遍,利用了类型推论---即编译器会根据传入的参数自动的帮我们确定T的类型。
function ssssss<T>(arg: T[]): T[] {
console.log(arg.length);
return arg;
}
function bbbbb<T>(arg: Array<T>): Array<T> {
console.log(arg.length);
return arg;
}