# typescirpt hater learn typescript: 2-1, before infer (generic, condition type, mapped type, keyof, typeof )
### generic
``` ts
type Cat = { name: string; age: number };
type CatT<T> = { name: string; age: T };
let c: CatT<number>;
let c2: CatT<string>;
```
### condition type (typescript if-else statement)
```ts=
type BooleanN<T> = T extends number ? true : false;
let b1: BooleanN<number>;
let b2: BooleanN<string>;
type isTwo<T> = T extends 2 ? true : false;
let i1: isTwo<2>;
let i2: isTwo<100>;
```
### [build-in utilty type](https://www.typescriptlang.org/docs/handbook/utility-types.html) (generic + condition type)
```ts
// type Exclude<T, U> = T extends U ? never : T;
interface Animal {}
interface Dog extends Animal {}
let e1: Exclude<string, number>;
let e2: Exclude<Dog, Animal>;
// Extract, NonNullable ....
```
### keyof (取出物件型別的 key,並建立成一個新的 type)
```ts
type Cat = {
name: string,
age: number,
}
type CatProp = keyof Cat;
let cp:CatProp;
type ArrProp = keyof [];
type StringProp = keyof string;
```
### Index signature / mapped type
```ts
type Cat = {
name: string;
age: number;
};
// type CatMap = {
// a: Cat,
// b: Cat,
// }
// Index signature
type CatMap = { [x: string]: Cat };
let cm: CatMap = {
a: { name: 'tom', age: 16 },
b: { name: 'john', age: 12 },
};
type CatMap2<T> = { [x: string]: T };
let cm2: CatMap2<Cat> = {
a: { name: 'tom', age: 16 },
b: { name: 'john', age: 12 },
};
// mapped type
// loops over all of the keys 'a', 'b'
type CatMap3 = { [x in 'a' | 'b']: Cat };
let cm3: CatMap3 = {
a: { name: 'tom', age: 16 },
b: { name: 'john', age: 12 },
};
type CatMap4<T extends string, U> = { [x in T]: U };
type cm4 = CatMap4<'a' | 'b', Cat>;
let cm4Obj: cm4 = {
a: { name: 'tom', age: 16 },
b: { name: 'john', age: 12 },
};
// keyof + mapped type ?
type Person = { name: string };
type WhatIsThis = keyof { [x: string]: Person };
type WhatIsThis2 = keyof { [y: number]: Person };
let w: WhatIsThis;
// so ...
type DD2 = keyof { [x: string]: object };
type DD3 = keyof { [x: string]: boolean };
type DD4 = keyof { [y: string]: Cat };
type DD5 = keyof { [y: string]: object };
type DD6 = keyof { [y: string]: boolean };
```
### Pick (mapped type + keyof)
```ts
type Cat = {
name: string,
age: number,
weight: number,
}
// type Pick<T, K extends keyof T> = {
// [P in K]: T[P];
// };
type NA = Pick<Cat, "name" | "age">;
```
### typeof
``` ts
const cat = {
name: 'kuro'
age: 10
}
type Cat = typeof cat;
let c:Cat;
type CatN = typeof cat['name']
```
### keyof + typeof combine
```ts=
const cat = {
name: 'kuro',
age: 10
}
type CatProp = keyof typeof cat;
type CatPropType = typeof cat[keyof typeof cat];
```