|
| 1 | +import { |
| 2 | + ComponentPropsOptions, |
| 3 | + ExtractPropTypes, |
| 4 | +} from '@vue/composition-api' |
| 5 | + |
| 6 | +export type ObjectEmitsOptions = Record< |
| 7 | +string, |
| 8 | +((...args: any[]) => any) | null |
| 9 | +> |
| 10 | + |
| 11 | +export type EmitsOptions = ObjectEmitsOptions | string[] |
| 12 | + |
| 13 | +export type EmitsToProps<T extends EmitsOptions> = T extends string[] |
| 14 | + ? { |
| 15 | + [K in string & `on${Capitalize<T[number]>}`]?: (...args: any[]) => any |
| 16 | + } |
| 17 | + : T extends ObjectEmitsOptions |
| 18 | + ? { |
| 19 | + [K in string & |
| 20 | + `on${Capitalize<string & keyof T>}`]?: K extends `on${infer C}` |
| 21 | + ? T[Uncapitalize<C>] extends null |
| 22 | + ? (...args: any[]) => any |
| 23 | + : ( |
| 24 | + ...args: T[Uncapitalize<C>] extends (...args: infer P) => any |
| 25 | + ? P |
| 26 | + : never |
| 27 | + ) => any |
| 28 | + : never |
| 29 | + } |
| 30 | + : {} |
| 31 | + |
| 32 | +export type UnionToIntersection<U> = ( |
| 33 | + U extends any ? (k: U) => void : never |
| 34 | +) extends (k: infer I) => void |
| 35 | + ? I |
| 36 | + : never |
| 37 | + |
| 38 | +export type EmitFn< |
| 39 | + Options = ObjectEmitsOptions, |
| 40 | + Event extends keyof Options = keyof Options |
| 41 | +> = Options extends Array<infer V> |
| 42 | + ? (event: V, ...args: any[]) => void |
| 43 | + : {} extends Options // if the emit is empty object (usually the default value for emit) should be converted to function |
| 44 | + ? (event: string, ...args: any[]) => void |
| 45 | + : UnionToIntersection< |
| 46 | + { |
| 47 | + [key in Event]: Options[key] extends (...args: infer Args) => any |
| 48 | + ? (event: key, ...args: Args) => void |
| 49 | + : (event: key, ...args: any[]) => void |
| 50 | + }[Event] |
| 51 | + > |
| 52 | + |
| 53 | +declare global { |
| 54 | + /** |
| 55 | + * Vue `<script setup>` compiler macro for declaring component props. The |
| 56 | + * expected argument is the same as the component `props` option. |
| 57 | + * |
| 58 | + * Example runtime declaration: |
| 59 | + * ```js |
| 60 | + * // using Array syntax |
| 61 | + * const props = defineProps(['foo', 'bar']) |
| 62 | + * // using Object syntax |
| 63 | + * const props = defineProps({ |
| 64 | + * foo: String, |
| 65 | + * bar: { |
| 66 | + * type: Number, |
| 67 | + * required: true |
| 68 | + * } |
| 69 | + * }) |
| 70 | + * ``` |
| 71 | + * |
| 72 | + * Equivalent type-based decalration: |
| 73 | + * ```ts |
| 74 | + * // will be compiled into equivalent runtime declarations |
| 75 | + * const props = defineProps<{ |
| 76 | + * foo?: string |
| 77 | + * bar: number |
| 78 | + * }>() |
| 79 | + * ``` |
| 80 | + * |
| 81 | + * This is only usable inside `<script setup>`, is compiled away in the |
| 82 | + * output and should **not** be actually called at runtime. |
| 83 | + */ |
| 84 | + // overload 1: runtime props w/ array |
| 85 | + export function defineProps<PropNames extends string = string>( |
| 86 | + props: PropNames[] |
| 87 | + ): Readonly<{ [key in PropNames]?: any }> |
| 88 | + // overload 2: runtime props w/ object |
| 89 | + export function defineProps< |
| 90 | + PP extends ComponentPropsOptions = ComponentPropsOptions |
| 91 | + >(props: PP): Readonly<ExtractPropTypes<PP>> |
| 92 | + // overload 3: typed-based declaration |
| 93 | + export function defineProps<TypeProps>(): Readonly<TypeProps> |
| 94 | + |
| 95 | + /** |
| 96 | + * Vue `<script setup>` compiler macro for declaring a component's emitted |
| 97 | + * events. The expected argument is the same as the component `emits` option. |
| 98 | + * |
| 99 | + * Example runtime declaration: |
| 100 | + * ```js |
| 101 | + * const emit = defineEmits(['change', 'update']) |
| 102 | + * ``` |
| 103 | + * |
| 104 | + * Example type-based decalration: |
| 105 | + * ```ts |
| 106 | + * const emit = defineEmits<{ |
| 107 | + * (event: 'change'): void |
| 108 | + * (event: 'update', id: number): void |
| 109 | + * }>() |
| 110 | + * |
| 111 | + * emit('change') |
| 112 | + * emit('update', 1) |
| 113 | + * ``` |
| 114 | + * |
| 115 | + * This is only usable inside `<script setup>`, is compiled away in the |
| 116 | + * output and should **not** be actually called at runtime. |
| 117 | + */ |
| 118 | + // overload 1: runtime emits w/ array |
| 119 | + export function defineEmits<EE extends string = string>( |
| 120 | + emitOptions: EE[] |
| 121 | + ): EmitFn<EE[]> |
| 122 | + export function defineEmits<E extends EmitsOptions = EmitsOptions>( |
| 123 | + emitOptions: E |
| 124 | + ): EmitFn<E> |
| 125 | + export function defineEmits<TypeEmit>(): TypeEmit |
| 126 | + |
| 127 | + /** |
| 128 | + * Vue `<script setup>` compiler macro for declaring a component's exposed |
| 129 | + * instance properties when it is accessed by a parent component via template |
| 130 | + * refs. |
| 131 | + * |
| 132 | + * `<script setup>` components are closed by default - i.e. varaibles inside |
| 133 | + * the `<script setup>` scope is not exposed to parent unless explicitly exposed |
| 134 | + * via `defineExpose`. |
| 135 | + * |
| 136 | + * This is only usable inside `<script setup>`, is compiled away in the |
| 137 | + * output and should **not** be actually called at runtime. |
| 138 | + */ |
| 139 | + export function defineExpose(exposed?: Record<string, any>): void |
| 140 | + |
| 141 | + type NotUndefined<T> = T extends undefined ? never : T |
| 142 | + |
| 143 | + type InferDefaults<T> = { |
| 144 | + [K in keyof T]?: NotUndefined<T[K]> extends |
| 145 | + | number |
| 146 | + | string |
| 147 | + | boolean |
| 148 | + | symbol |
| 149 | + | Function |
| 150 | + ? NotUndefined<T[K]> |
| 151 | + : (props: T) => NotUndefined<T[K]> |
| 152 | + } |
| 153 | + |
| 154 | + type PropsWithDefaults<Base, Defaults> = Base & |
| 155 | + { |
| 156 | + [K in keyof Defaults]: K extends keyof Base ? NotUndefined<Base[K]> : never |
| 157 | + } |
| 158 | + |
| 159 | + /** |
| 160 | + * Vue `<script setup>` compiler macro for providing props default values when |
| 161 | + * using type-based `defineProps` decalration. |
| 162 | + * |
| 163 | + * Example usage: |
| 164 | + * ```ts |
| 165 | + * withDefaults(defineProps<{ |
| 166 | + * size?: number |
| 167 | + * labels?: string[] |
| 168 | + * }>(), { |
| 169 | + * size: 3, |
| 170 | + * labels: () => ['default label'] |
| 171 | + * }) |
| 172 | + * ``` |
| 173 | + * |
| 174 | + * This is only usable inside `<script setup>`, is compiled away in the output |
| 175 | + * and should **not** be actually called at runtime. |
| 176 | + */ |
| 177 | + export function withDefaults<Props, Defaults extends InferDefaults<Props>>( |
| 178 | + props: Props, |
| 179 | + defaults: Defaults, |
| 180 | + ): PropsWithDefaults<Props, Defaults> |
| 181 | +} |
0 commit comments