typescript高级编程(一)
typescript 差缺补漏
交叉点类型
交集类型是将多个类型组合为一种的方法,就是多个类型的合并
type LeftType = {
id: number
left: string
}
type RightType = {
id: number
right: string
}
type IntersectionType = LeftType & RightType
function showType(args: IntersectionType) {
console.log(args)
}
showType({ id: 1, left: "test", right: "test" })
// Output: {id: 1, left: "test", right: "test"}
联合类型用的比较多
let a:number|string;
通用类型感觉这个很厉害
构造泛型类型,用方括号T作为参数传递
interface GenericType<T> {
id: number,
name: T
}
function showType(args: GenericType<string>) {
console.log(args);
}
function showTypeTwo(args: GenericType<number>) {
console.log(args);
}
showType({id: 10, name: 'xxx'});
showTypeTwo({id: 10, name: 20});
我以前以为只能用T,今天看了大佬的代码,发现原来T只是一个符号,学习到了
interface GenericType<T,D>{
id:T,
name:D
}
function showType(args: GenericType<number, string>) {
console.log(args);
}
showType({id:20, name: 'ss'});
function showTypeTwo(args: GenericType<number, Array<string>>) {
}
showTypeTwo({id:10, name: ['a', 'b', 'c']})
可选
Partial<T>
interface PartialType { id: number firstName: string lastName: string } function showType(args: Partial<PartialType>) { console.log(args) } showType({ id: 1 }) // Output: {id: 1} showType({ firstName: "John", lastName: "Doe" }) // Output: {firstName: "John", lastName: "Doe"}
必传
Required<T>
提供的T需要传所有类型的属性
interface RequiredType { id: number firstName?: string lastName?: string } function showType(args: Required<RequiredType>) { console.log(args) } showType({ id: 1, firstName: "John", lastName: "Doe" }) // Output: { id: 1, firstName: "John", lastName: "Doe" } showType({ id: 1 }) //报错啦
只读
Readonly<T>
T无法使用新值重新分配
interface ReadonlyType { id: number name: string } function showType(args: Readonly<ReadonlyType>) { args.id = 4 console.log(args) } showType({ id: 1, name: "Doe" }) // error 报错了,他的值都不能被修改 不过下面这样写也不错 interface ReadonlyType { readonly id: number name: string }
忽略
Omit<T,k>
将K从属性T 删除
简单的说就是我输入类型不能带入k,不然会报错
interface PickType { id: number firstName: string lastName: string } function showType(args: Omit<PickType, "firstName" | "lastName">) { console.log(args) } showType({id: 12}) // 正常 // 带有firstName 或者 lastName就会报错
挑选
Pick<T,K>
T中要有属性k
interface PickType { id: number firstName: string lastName: string, name: string } function showType(args: Pick<PickType, 'firstName' | 'lastName'>) { console.log(args); } showType({lastName: 'xx', firstName: 'xx'}); showType({lastName: 'xx', firstName: 'xx', id: 12}); // 报错 showType({lastName: 'xx', firstName: 'xx', name:'xx'}); // 报错
仔细的理解了下,就是类型中只能包含
firstName 和 lastName
,所以可以理解成挑选k就是你要选择的属性,你可以用
|
进行分隔选择多个字段
记录
Record<K,T>
将一个类型的属性K映射到另一个类型的属性
interface EmployeeType { id: number fullname: string role: string } let employees: Record<number, EmployeeType> = { 0: { id: 1, fullname: "John Doe", role: "Designer" }, 1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" }, 2: { id: 3, fullname: "Sara Duckson", role: "Developer" }, } // 0: { id: 1, fullname: "John Doe", role: "Designer" }, // 1: { id: 2, fullname: "Ibrahima Fall", role: "Developer" }, // 2: { id: 3, fullname: "Sara Duckson", role: "Developer" }
映射类型
把每个属性转换为新类型
type StringMap<T> = { [P in keyof T]: string } function showType(arg: StringMap<{ id: number; name: string }>) { console.log(arg) } showType({name:'xx',id:'ss'}) //就是把已经的属性都转成string showType({ id: 1, name: "Test" }) // 会报错
类型防护
typeof
function showType(x: number | string) {
if (typeof x === "number") {
return `The result is ${x + x}`
}
throw new Error(`This operation can't be done on a ${typeof x}`)
}
showType("I'm not a number")
// Error: This operation can't be done on a string
showType(7)
// Output: The result is 14
instanceof
class Foo {
bar() {
return "Hello World"
}
}
class Bar {
baz = "123"
}
function showType(arg: Foo | Bar) {
if (arg instanceof Foo) {
console.log(arg.bar())
return arg.bar()
}
throw new Error("The type is not supported")
}
showType(new Foo())
// Output: Hello World
showType(new Bar())
// Error: The type is not supported
in
忽略的点看来我之前的写法没这种好
interface Bookes {
id: number,
name: string
}
books: Bookes[] = [
{id: 1, name: 'Angular'},
{id: 2, name: 'Typescript'},
{id: 3, name: 'Javascript'},
{id: 4, name: 'HTML'}
];
发现一个奇怪的!
!只是用来判断null和undefined;
as则可用于变更(缩小或者放大都可以)类型检测范围
as和!用于属性的读取,都可以缩小类型检查范围,都做判空用途时是等价的。只是!具体用于告知编译器此值不可能为空值(null和undefined),而as不限于此
?可用于属性的定义和读取,读取时告诉编译器此值可能为空值(null和undefined),需要做判断。
interface InterArray {
children?: InterArrayOne
}
interface InterArrayOne {
name: string,
age: number
}
export class OneComponent implements OnInit {
public a: (InterArrayOne & InterArray) [] = [{
name: 'xx',
age: 12,
children: {
name: 'aaa',
age: 12
}
},
{
name: 'aa',
age: 13,
},
];
add(): void {
for (let i = 0; i < this.a.length; i++) {
console.log(this.a[i]!.children?.name);
}
}
ngOnInit(): void {
this.add();
}
}
类型谓词
function isString(x: any): x is string {
return typeof x === 'string';
}
null!
其实本质上都是null但是加上!会具有语义化些,这个是问大佬们才知道的
undefined! 同理也是false
决定自己的高度的是你的态度,而不是你的才能
记得我们是终身初学者和学习者
总有一天我也能成为大佬