- 使用注释,方便开发者理解接口/类型的含义
interface PersonInfo {
name: string;
age: number;
}
const person: PersonInfo = {
name: 'test',
age: 18,
};
- 巧用typeof
1.类型反推
const person = {
name: 'test',
age: 18,
};
type PersonInfo = typeof person;
2.类型判断
const getPadding = (a: number | string) => {
if (typeof a === 'number') {
return a;
} else {
return Number(a);
}
};
3.结合函数获取返回类型
const dialog: ReturnType<typeof useDialog> = useDialog();
4.获取组件实例
const messageProviderRef = ref<InstanceType<typeof NMessageProvider> | null>(null);
- 使用keyof查找key值
1.获取interface里的key
export interface IEvents {
trigger: Trigger;
action: Action;
}
const events: { [key in keyof IEvents]: IEvents[key] }[] = [];
2.泛型+keyof
interface API {
'/user': { name: string },
'/menu': { foods: Food[] },
}
const get = <URL extends keyof API>(url: URL): Promise<API[URL]> => {
return fetch(url).then(res => res.json())
}
- 使用类型查找
interface PersonInfo {
name: string;
age: number;
}
const name: PersonInfo['name'] = 'test';
type DataTableThemeOverrides = NonNullable<DataTableProps['themeOverrides']>;
- 类型体操进行接口复用
1.使用Omit复用接口
interface TrafficLight {
center: LatLng
lanes?: string[]
light_id: string
signals: TrafficLightSignal[]
}
type TrafficLightObject = Omit<TrafficLight, 'center'>
2.结合Record
interface TrafficLight {
center: LatLng
lanes?: string[]
light_id: string
signals: TrafficLightSignal[]
}
type TrafficLights = Record<TrafficLight['light_id'], Omit<TrafficLight, 'light_id'>>
- 适当时可用Record
type AnimalType = 'cat' | 'dog' | 'frog';
interface AnimalDescription { name: string, icon: string }
const AnimalMap: Record<AnimalType, AnimalDescription> = {
cat: { name: '猫', icon: ' '},
dog: { name: '狗', icon: ' ' },
forg: { name: '蛙', icon: ' ' },
};
- 巧用as const 参考const-assertions
1.定值的时候可用
export const COMMON = {
groupOptions: ['planning', 'perception', 'integration', 'map'] as const,
testingStages: [
'basic',
'active',
'advanced',
'super',
] as const
};
2.[a, b] as const
const a = [1, 'test']
const b = [1, 'test'] as const
[1, ''] 会被推导为类型 (number | string)[],而加 as const 可推断为元组,可用于解决watch多个type错误问题
watch(
() => [routeRef.value, activeEntityCenterRef.value] as const,
([{ id, type, name }]) => {
},
{
immediate: true,
},
);
3.Vue组件修改props问题
type NumberOrNumberString = PropType<string | number | undefined>;
const props = {
height: [Number, String] as NumberOrNumberString,
} as const;
export default defineComponent({
props,
setup() {
const changeHeight = () => {
console.log(props.height);
props.height = 120;
}
}
})
至于setup语法糖则默认帮我们置为readonly了
const props = defineProps({
foo: String,
age: Number,
});
or
const props = defineProps<{
foo: string;
age: number;
}>();
props.foo = '123';
- 类型收窄
1.使用as,当你知道类型时可用使用as进行类型收窄
interface Cat {
name: string;
run(): void;
}
interface Fish {
name: string;
swim(): void;
}
const canRun = (data: Cat | Fish) => {
(data as Cat).run();
};
更好的断言
const isCat = (animal: Cat | Fish): animal is Cat => {
return typeof (animal as Cat).run === 'function';
};
2.类型守卫
利用typeof
type Foo = string | number;
const judgeType = (data: Foo) => {
if (typeof data === 'string') {
return data;
} else if (typeof data === 'number') {
return data + '';
} else {
return '123';
}
};
instanceof判断类型
class Man {
name = 'John';
}
class Woman {
age = 20;
}
const getName = (human: Man | Woman) => {
if (human instanceof Man) {
console.log(human.name);
} else {
console.log(human.age);
}
};
利用in判断
interface A {
a: string;
}
interface B {
b: number;
}
function getVar(data: A | B) {
if ('a' in data) {
console.log(data.a);
} else {
console.log(data.b);
}
}
3.双重断言(慎用,编译器会相信你的断言,如果类型有问题是检测不出来的)
const handleEvent = (event: Event) => {
const element = event as unknown as HTMLElement;
};
- 没有合适的类型时自己写类型,这里查看官方类型
比如你传入的类型可能是数组也可能是普通类型
type MaybeArray<T> = T | T[];
const getMeters = (meters: MaybeArray<number>) => {
};
比如你想要进行camelize
interface Obj {
lane_id: string;
name: string;
}
type CamelizeKey<T> = T extends `${infer Left}_${infer F}${infer Right}`
? F extends Uppercase<F>
? `${Left}_${CamelizeString<`${F}${Right}`>}`
: `${Left}${Uppercase<F>}${CamelizeString<Right>}`
: T;
type CamelizeObj<T extends Object> = {
[Key in keyof T as CamelizeKey<Key>]: T[Key];
};
type UpperObj = CamelizeObj<Obj>;
- 学会使用infer(类型推断),这里写的还不错
infer表示在 extends 条件语句中待推断的类型变量
type ParamType<T> = T extends (...args: infer P) => any ? P : T;
在这个条件语句 T extends (...args: infer P) => any ? P : T 中,infer P 表示待推断的函数参数。
整句表示为:如果 T 能赋值给 (...args: infer P) => any,则结果是 (...args: infer P) => any 类型中的参数 P,否则返回为 T。
example:
interface User {
name: string;
age: number;
}
type Func = (user: User) => void;
type Param = ParamType<Func>;
type AA = ParamType<string>;