Skip to content

Commit

Permalink
refactor(define-props-refs): import withDefault manually
Browse files Browse the repository at this point in the history
  • Loading branch information
sxzz committed Jun 8, 2023
1 parent 38b579c commit ee4e093
Show file tree
Hide file tree
Showing 23 changed files with 205 additions and 93 deletions.
8 changes: 8 additions & 0 deletions .changeset/shy-buckets-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@vue-macros/define-props-refs': minor
'@vue-macros/common': minor
'unplugin-vue-macros': minor
'@vue-macros/volar': minor
---

should import withDefault manually when using `definePropsRefs`
17 changes: 17 additions & 0 deletions docs/macros/define-props-refs.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ console.log(foo.value, bar.value)
</script>
```

## With Default Value

```vue {2-3,8}
<script setup lang="ts">
import { withDefaults } from 'unplugin-vue-macros/macros' assert { type: 'macro' }
const { foo } = withDefaults(
definePropsRefs<{
foo?: string
}>(),
{ foo: 'test' }
)
// ⬇️ Ref<string>
console.log(foo.value)
</script>
```

## Volar Configuration

```jsonc {6}
Expand Down
17 changes: 17 additions & 0 deletions docs/zh-CN/macros/define-props-refs.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ console.log(foo.value, bar.value)
</script>
```

## 默认值

```vue {2-3,8}
<script setup lang="ts">
import { withDefaults } from 'unplugin-vue-macros/macros' assert { type: 'macro' }
const { foo } = withDefaults(
definePropsRefs<{
foo?: string
}>(),
{ foo: 'test' }
)
// ⬇️ Ref<string>
console.log(foo.value)
</script>
```

## Volar 配置

```jsonc {6}
Expand Down
2 changes: 1 addition & 1 deletion packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"@babel/types": "^7.22.4",
"@rollup/pluginutils": "^5.0.2",
"@vue/compiler-sfc": "^3.3.4",
"ast-kit": "^0.5.1",
"ast-kit": "^0.5.2",
"local-pkg": "^0.4.3",
"magic-string-ast": "^0.1.2"
},
Expand Down
7 changes: 7 additions & 0 deletions packages/common/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,10 @@ export type MarkRequired<T, K extends keyof T> = Omit<T, K> &
Required<Pick<T, K>>

export type Overwrite<T, U> = Pick<T, Exclude<keyof T, keyof U>> & U

export type RecordToUnion<T extends Record<string, any>> = T[keyof T]
export type UnionToIntersection<U> = (
U extends unknown ? (arg: U) => 0 : never
) extends (arg: infer I) => 0
? I
: never
25 changes: 20 additions & 5 deletions packages/common/src/vue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import {
type SFCScriptBlock as SFCScriptBlockMixed,
parse,
} from '@vue/compiler-sfc'
import { type Program } from '@babel/types'
import { type MagicStringBase } from 'magic-string-ast'
import { babelParse, getLang } from 'ast-kit'
import { type Node, type Program } from '@babel/types'
import { type MagicString, type MagicStringBase } from 'magic-string-ast'
import { babelParse, getLang, resolveString } from 'ast-kit'
import { REGEX_VUE_SFC } from './constants'

export type SFCScriptBlock = Omit<
Expand Down Expand Up @@ -51,11 +51,15 @@ export function parseSFC(code: string, id: string): SFC {
errors,
getSetupAst() {
if (!descriptor.scriptSetup) return
return babelParse(descriptor.scriptSetup.content, lang)
return babelParse(descriptor.scriptSetup.content, lang, {
plugins: [['importAttributes', { deprecatedAssertSyntax: true }]],
})
},
getScriptAst() {
if (!descriptor.script) return
return babelParse(descriptor.script.content, lang)
return babelParse(descriptor.script.content, lang, {
plugins: [['importAttributes', { deprecatedAssertSyntax: true }]],
})
},
}
}
Expand Down Expand Up @@ -96,3 +100,14 @@ export function addNormalScript({ script, lang }: SFC, s: MagicStringBase) {
},
}
}

export function removeMacroImport(node: Node, s: MagicString, offset: number) {
if (
node.type === 'ImportDeclaration' &&
node.attributes?.some(
(attr) =>
resolveString(attr.key) === 'type' && attr.value.value === 'macro'
)
)
s.removeNode(node, { offset })
}
2 changes: 0 additions & 2 deletions packages/define-props-refs/macros-global.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
declare const definePropsRefs: typeof import('./macros').definePropsRefs
// @ts-ignore
declare const withDefaults: typeof import('./macros').withDefaults
23 changes: 6 additions & 17 deletions packages/define-props-refs/macros.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export declare type PropRefs<T> = {
[K in keyof T]-?: ComputedRef<DeepReadonly<T[K]>>
}

export declare type NotUndefined<T> = T extends undefined ? never : T
export type NotUndefined<T> = T extends undefined ? never : T

export declare type InferDefault<P, T> = T extends
declare type InferDefault<P, T> = T extends
| null
| number
| string
Expand All @@ -22,31 +22,20 @@ export declare type InferDefault<P, T> = T extends
? T | ((props: P) => T)
: (props: P) => T

export declare type InferDefaults<T> = {
declare type InferDefaults<T> = {
[K in keyof T]?: InferDefault<T, NotUndefined<T[K]>>
}

export declare type PropsWithDefaults<Base, Defaults> = Base & {
[K in keyof Defaults]: K extends keyof Base
? Defaults[K] extends undefined
? Base[K]
: NotUndefined<Base[K]>
: never
}

export declare function withDefaults<
Props,
Defaults extends InferDefaults<Props>
>(props: Props, defaults: Defaults): PropsWithDefaults<Props, Defaults>

export declare function withDefaults<
PropsWithRefs extends PropRefs<Record<string, any>>,
Defaults extends InferDefaults<Props>,
Props = {
-readonly [K in keyof PropsWithRefs]: PropsWithRefs[K] extends Readonly<
Ref<infer T>
>
? T
? K extends keyof Defaults
? NotUndefined<T>
: T
: PropsWithRefs[K]
}
>(props: PropsWithRefs, defaults: Defaults): PropRefs<Props>
Expand Down
3 changes: 3 additions & 0 deletions packages/define-props-refs/src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
importHelperFn,
isCallOf,
parseSFC,
removeMacroImport,
walkAST,
} from '@vue-macros/common'
import { type CallExpression, type Node } from '@babel/types'
Expand All @@ -24,6 +25,8 @@ export function transformDefinePropsRefs(code: string, id: string) {

walkAST<Node>(setupAst, {
enter(node) {
removeMacroImport(node, s, offset)

if (isCallOf(node, WITH_DEFAULTS) && node.arguments) {
processDefinePropsRefs(node.arguments[0] as CallExpression, node)
this.skip()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,20 @@ expectTypeOf(bar).toEqualTypeOf<ComputedRef<number>>()
exports[`fixtures > ./fixtures/with-defaults.vue 1`] = `
"<script setup lang=\\"ts\\">
const __MACROS_props = withDefaults(defineProps<{
foo: string
bar: number[]
foo?: string
bar?: number[]
}>(), {
foo: 'foo',
bar: () => [1, 2, 3],
})
import { toRefs as __MACROS_toRefs } from \\"vue\\";
import { expectTypeOf } from 'expect-type'
import { ComputedRef } from 'vue'
const { foo, bar } = __MACROS_toRefs(__MACROS_props)
expectTypeOf(foo).toEqualTypeOf<ComputedRef<string>>()
expectTypeOf(bar).toEqualTypeOf<ComputedRef<readonly number[]>>()
expectTypeOf(bar).toEqualTypeOf<ComputedRef<readonly number[] | undefined>>()
</script>
"
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ interface Props {
}
}
// definePropsRefs
const props = withDefaults(defineProps<Props>(), {
modelValue: () => ({
signatureAppearance: 'none',
Expand Down
8 changes: 4 additions & 4 deletions packages/define-props-refs/tests/fixtures/with-defaults.vue
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<script setup lang="ts">
import { expectTypeOf } from 'expect-type'
import { ComputedRef } from 'vue'
import { withDefaults } from '../../macros' assert { type: 'macro' }
const { foo, bar } = withDefaults(
definePropsRefs<{
foo: string
bar: number[]
foo?: string
bar?: number[]
}>(),
{
foo: 'foo',
bar: () => [1, 2, 3],
}
)
expectTypeOf(foo).toEqualTypeOf<ComputedRef<string>>()
expectTypeOf(bar).toEqualTypeOf<ComputedRef<readonly number[]>>()
expectTypeOf(bar).toEqualTypeOf<ComputedRef<readonly number[] | undefined>>()
</script>
2 changes: 0 additions & 2 deletions packages/define-props-refs/vue2-macros-global.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
declare const definePropsRefs: typeof import('./vue2-macros').definePropsRefs
// @ts-ignore
declare const withDefaults: typeof import('./vue2-macros').withDefaults
22 changes: 6 additions & 16 deletions packages/define-props-refs/vue2-macros.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ export declare type PropRefs<T> = {
[K in keyof T]-?: ComputedRef<DeepReadonly<T[K]>>
}

export declare type NotUndefined<T> = T extends undefined ? never : T
export type NotUndefined<T> = T extends undefined ? never : T

export declare type InferDefault<P, T> = T extends
declare type InferDefault<P, T> = T extends
| null
| number
| string
Expand All @@ -24,33 +24,23 @@ export declare type InferDefault<P, T> = T extends
? T | ((props: P) => T)
: (props: P) => T

export declare type InferDefaults<T> = {
declare type InferDefaults<T> = {
[K in keyof T]?: InferDefault<T, NotUndefined<T[K]>>
}

export declare type PropsWithDefaults<Base, Defaults> = Base & {
[K in keyof Defaults]: K extends keyof Base
? Defaults[K] extends undefined
? Base[K]
: NotUndefined<Base[K]>
: never
}

export declare function withDefaults<
PropsWithRefs extends PropRefs<Record<string, any>>,
Defaults extends InferDefaults<Props>,
Props = {
-readonly [K in keyof PropsWithRefs]: PropsWithRefs[K] extends Readonly<
Ref<infer T>
>
? T
? K extends keyof Defaults
? NotUndefined<T>
: T
: PropsWithRefs[K]
}
>(props: PropsWithRefs, defaults: Defaults): PropRefs<Props>
export declare function withDefaults<
Props,
Defaults extends InferDefaults<Props>
>(props: Props, defaults: Defaults): PropsWithDefaults<Props, Defaults>

export declare function definePropsRefs<PropNames extends string = string>(
props: PropNames[]
Expand Down
18 changes: 17 additions & 1 deletion packages/macros/macros.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
import {
definePropsRefs,
type withDefaults as withDefaultsDefinePropsRefs,
} from '@vue-macros/define-props-refs/macros'
import {
type RecordToUnion,
type UnionToIntersection,
} from '@vue-macros/common'

export * from '@vue-macros/define-emit/macros'
export * from '@vue-macros/define-models/macros'
export * from 'unplugin-vue-define-options/macros'
export * from '@vue-macros/define-prop/macros'
export * from '@vue-macros/define-props/macros'
export * from '@vue-macros/define-props-refs/macros'
export * from '@vue-macros/define-render/macros'
export * from '@vue-macros/define-slots/macros'
export * from '@vue-macros/reactivity-transform/macros'
export * from '@vue-macros/setup-component/macros'
export * from '@vue-macros/short-emits/macros'
export { definePropsRefs }

interface WithDefaultsMap {
definePropsRefs: typeof withDefaultsDefinePropsRefs
}

type WithDefaults = UnionToIntersection<RecordToUnion<WithDefaultsMap>>
export declare const withDefaults: WithDefaults
18 changes: 17 additions & 1 deletion packages/macros/vue2-macros.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,26 @@
import {
definePropsRefs,
type withDefaults as withDefaultsDefinePropsRefs,
} from '@vue-macros/define-props-refs/vue2-macros'
import {
type RecordToUnion,
type UnionToIntersection,
} from '@vue-macros/common'

export * from '@vue-macros/define-emit/macros'
export * from '@vue-macros/define-models/macros'
export * from 'unplugin-vue-define-options/macros'
export * from '@vue-macros/define-prop/macros'
export * from '@vue-macros/define-props/vue2-macros'
export * from '@vue-macros/define-props-refs/vue2-macros'
export * from '@vue-macros/define-render/vue2-macros'
export * from '@vue-macros/define-slots/macros'
export * from '@vue-macros/reactivity-transform/vue2-macros'
export * from '@vue-macros/short-emits/macros'
export { definePropsRefs }

interface WithDefaultsMap {
definePropsRefs: typeof withDefaultsDefinePropsRefs
}

type WithDefaults = UnionToIntersection<RecordToUnion<WithDefaultsMap>>
export declare const withDefaults: WithDefaults
11 changes: 5 additions & 6 deletions packages/short-emits/macros.d.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
type RecordToUnion<T extends Record<string, any>> = T[keyof T]
type UnionToIntersection<U> = (
U extends unknown ? (arg: U) => 0 : never
) extends (arg: infer I) => 0
? I
: never
import {
type RecordToUnion,
type UnionToIntersection,
} from '@vue-macros/common'

export type ShortEmits<T extends Record<string, any>> = UnionToIntersection<
RecordToUnion<{
[K in keyof T]: T[K] extends (...args: any[]) => any
Expand Down

0 comments on commit ee4e093

Please sign in to comment.