rfc 中類型推導部分 Type Inferencehtml
createComponent({
props: {
foo: {
type: String,
required: true
},
bar: {
type: Number
},
boo: Boolean,
options: (null as any) as { msg: string },
requiredOptions: {
type: (null as any) as { msg: string },
required: true
}
} as const,
setup(props) {
props.foo; // string
props.bar; // number | undefined
props.boo; // boolean | undefined
props.options; // {msg: string } | undefined
props.requiredOptions; // {msg: string }
}
});
複製代碼
String
-> string
、 Number
-> number
、 Boolean
-> boolean
在 ts 中vue
String
對應的類型是StringConstructor
Number
對應的類型是NumberConstructor
Boolean
對應的類型是BooleanConstructor
可是,咱們想要實現的是轉換成小寫的string | number | boolean
git
因此咱們寫個泛型來轉換github
type NormalizeType<T> = T extends StringConstructor
? string
: T extends NumberConstructor
? number
: T extends BooleanConstructor
? boolean
: T;
複製代碼
playground 預覽連接typescript
type BuiltInType<T> =
| StringConstructor
| NumberConstructor
| BooleanConstructor
| T;
複製代碼
留個泛型是給複雜類型作兼容 rfc 複雜的 prop 類型api
createComponent
函數接收的props
類型type DefaultType<T> = {
[key: string]:
| {
type?: BuiltInType<T>;
require?: boolean;
}
| BuiltInType<T>;
};
複製代碼
props
類型計算出來setup
函數接收的形參props
類型type ReflexType<T> = {
[key in keyof T]: T[key] extends { type: infer TYPE; required: true }
? NormalizeType<TYPE>
: T[key] extends { type: infer TYPE }
? NormalizeType<TYPE> | undefined
: NormalizeType<T[key]> | undefined
};
複製代碼
createComponent
函數定義function createComponent<T extends DefaultType<any>>(props: {
props: T;
setup(props: ReflexType<T>): any;
}) {}
複製代碼
type BuiltInType<T> =
| StringConstructor
| NumberConstructor
| BooleanConstructor
| T;
type NormalizeType<T> = T extends StringConstructor
? string
: T extends NumberConstructor
? number
: T extends BooleanConstructor
? boolean
: T;
type ReflexType<T> = {
[key in keyof T]: T[key] extends { type: infer TYPE; required: true }
? NormalizeType<TYPE>
: T[key] extends { type: infer TYPE }
? NormalizeType<TYPE> | undefined
: NormalizeType<T[key]> | undefined
};
type DefaultType<T> = {
[key: string]: { type?: BuiltInType<T>; require?: boolean } | BuiltInType<T>;
};
function createComponent<T extends DefaultType<any>>(props: {
props: T;
setup(props: ReflexType<T>): any;
}) {}
createComponent({
props: {
foo: {
type: String,
required: true
},
bar: {
type: Number
},
boo: Boolean,
options: (null as any) as { msg: string },
requiredOptions: {
type: (null as any) as { msg: string },
required: true
}
} as const,
setup(props) {
props.foo;
props.bar;
props.boo;
props.options;
props.requiredOptions;
}
});
複製代碼