Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

types(defineComponent): Stricter Component Type + helpers #9556

Open
wants to merge 83 commits into
base: minor
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 75 commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
b256412
WIP: component helper types
pikax Nov 6, 2023
e1ef6a8
fix one issue
pikax Nov 6, 2023
fbd083b
working kinda
pikax Nov 6, 2023
8934665
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 6, 2023
e7c0383
add Extract component Options
pikax Nov 6, 2023
5f86b19
added types
pikax Nov 6, 2023
22c304c
more tests
pikax Nov 8, 2023
c2c0958
working few things
pikax Nov 8, 2023
3fbfe6f
cleanup
pikax Nov 8, 2023
99e48a7
removed unused
pikax Nov 8, 2023
1ce7234
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 8, 2023
d88f7af
remove stuff temp
pikax Nov 8, 2023
3b653cd
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 8, 2023
9b23cdf
small improvements
pikax Nov 9, 2023
de726ac
Merge branch 'main' into pikax/component_helper_types
pikax Nov 10, 2023
8b1faf7
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 10, 2023
ae7b51b
export LooseRequired
pikax Nov 10, 2023
9e67b17
WIP DefineComponentOptions type
pikax Nov 13, 2023
f6f82fa
WIP building
pikax Nov 14, 2023
0506beb
test passing
pikax Nov 14, 2023
3e29651
fix other issues
pikax Nov 14, 2023
48a0b08
remove render function type
pikax Nov 14, 2023
6d1db29
async component changes
pikax Nov 14, 2023
f47bc76
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 14, 2023
bbad2f8
support more overloads on defineComponet and also support VNode on h
pikax Nov 14, 2023
1d40c76
add vnode support
pikax Nov 15, 2023
998607e
few more changes
pikax Nov 15, 2023
4254fac
Merge branch 'main' into pikax/component_helper_types
pikax Nov 15, 2023
633b852
more work
pikax Nov 16, 2023
96f244a
more improvements
pikax Nov 16, 2023
aab3189
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 16, 2023
8a61db8
some improvements
pikax Nov 17, 2023
3d8a5c0
more improvements and add some comments
pikax Nov 18, 2023
ca626bf
more improvments
pikax Nov 18, 2023
b2c4a38
Merge branch 'main' into pikax/component_helper_types
pikax Nov 18, 2023
9853470
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 18, 2023
0d0bf05
fix componentSlots
pikax Nov 20, 2023
9ae88d3
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 20, 2023
f62ae36
support volar syntax for slots
pikax Nov 20, 2023
413d556
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 20, 2023
836a930
introducing DeclareComponent type
pikax Nov 20, 2023
8336ba5
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 20, 2023
77ca7b1
chore: renaming & lint
pikax Nov 21, 2023
bba1cde
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 21, 2023
ab9823d
fix test type
pikax Nov 21, 2023
c98c360
chore: some changes
pikax Nov 22, 2023
86826aa
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 22, 2023
92057db
some imrpovements
pikax Nov 22, 2023
b015918
chore: some improvements
pikax Nov 22, 2023
6819d05
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 22, 2023
f3119d4
types: change DefineComponent defaults to be more lenient
pikax Nov 23, 2023
53f2af0
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 23, 2023
018223d
chore: improve ComponentData
pikax Nov 23, 2023
5e9d759
Custom props
pikax Nov 24, 2023
73f52d3
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 24, 2023
bf6286d
kinda working
pikax Nov 25, 2023
aa91257
remov efunction
pikax Nov 25, 2023
bb4cf93
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 25, 2023
d483491
chore: fix tests
pikax Nov 28, 2023
b1094a6
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 28, 2023
b4b62d0
chore: render function
pikax Nov 28, 2023
46cc5cb
[autofix.ci] apply automated fixes
autofix-ci[bot] Nov 28, 2023
cc2ed2a
chore: remove comments
pikax Nov 28, 2023
e777107
Merge branch 'minor' into pikax/component_helper_types
pikax Dec 29, 2023
eaa2ded
type fixing
pikax Dec 29, 2023
e3d217b
fix tests
pikax Dec 29, 2023
e063b78
fix tests
pikax Dec 29, 2023
e8e937b
chore: review
pikax Dec 29, 2023
fb2e70b
chore: improve defineAsyncComponent types
pikax Dec 30, 2023
5c0c261
chore: improve tests for async component
pikax Dec 30, 2023
37ca2cb
chore: some improvements + tests
pikax Dec 31, 2023
e9c7dfc
added DeclareEmits and removed shortEmits type
pikax Jan 13, 2024
b56836f
EmitsOptions to support events
pikax Jan 13, 2024
f3b9c28
improve type resolution when using ComponentEmits on DeclareComponent
pikax Jan 13, 2024
3b307e3
chore: improve ObjectToProps, to keep the original type
pikax Jan 13, 2024
b8b99a8
chore: Added DynamicComponent type helper
pikax Jan 13, 2024
7866070
chore: fix typo
pikax Jan 13, 2024
c6c8caf
chore: add a few tests for DynamicComponent
pikax Jan 13, 2024
42301b3
chore: improve types
pikax Jan 16, 2024
3ff6732
chore: clean up types, prevent object properties being overridden
pikax Jan 16, 2024
39b9ade
chore: fix usage of ComponentProps on DeclareComponent
pikax Jan 17, 2024
5890e8c
chore: fix type inferrence on props
pikax Jan 17, 2024
bdc1d73
chore: improvements on resolving props
pikax Jan 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
23 changes: 22 additions & 1 deletion packages/dts-built-test/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,31 @@
import { defineComponent } from 'vue'
import { type PropType, defineComponent } from 'vue'

const _CustomPropsNotErased = defineComponent({
props: {},
setup() {},
})

export const RegularComponent = defineComponent({
props: {},
setup() {
return () => {}
},
})

type MyInterface =
| {
a: string
}
| { b: string }
export const RegularComponentProps = defineComponent({
props: {
a: Object as () => MyInterface,
b: Object as PropType<MyInterface>,
},
setup(props) {
return () => {}
},
})
// #8376
export const CustomPropsNotErased =
_CustomPropsNotErased as typeof _CustomPropsNotErased & {
Expand Down
161 changes: 70 additions & 91 deletions packages/dts-test/component.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,30 @@
import {
type Component,
type ComponentData,
type ComponentProps,
type ComponentPublicInstance,
type EmitsOptions,
type EmitsToProps,
type ExtractComponentEmitOptions,
type ExtractComponentSlotOptions,
type FunctionalComponent,
type PropType,
type Ref,
type SetupContext,
type ShallowUnwrapRef,
defineComponent,
ref,
toRefs,
} from 'vue'
import { type IsAny, describe, expectAssignable, expectType } from './utils'

declare function extractComponentOptions<
Props,
RawBindings,
Emits extends EmitsOptions | Record<string, any[]>,
Slots extends Record<string, any>,
>(
obj: Component<Props, RawBindings, any, any, any, Emits, Slots>,
): {
props: Props
emits: Emits
slots: Slots
rawBindings: RawBindings
setup: ShallowUnwrapRef<RawBindings>
declare function extractComponentOptions<T>(obj: T): {
props: ComponentProps<T>
emits: ExtractComponentEmitOptions<T>
slots: ExtractComponentSlotOptions<T>

data: ComponentData<T>
}

declare function extractComponentProps<T>(obj: T): ComponentProps<T>

describe('object props', () => {
interface ExpectedProps {
a?: number | undefined
Expand Down Expand Up @@ -163,6 +160,9 @@ describe('object props', () => {
expectType<ExpectedRefs['object']>(refs.object)
expectType<IsAny<typeof props.zzz>>(true)

// @ts-expect-error should not be any
expectType<string>(props)

return {
setupA: 1,
setupB: ref(1),
Expand All @@ -175,7 +175,9 @@ describe('object props', () => {
},
})

const { props, rawBindings, setup } = extractComponentOptions(MyComponent)
const { data } = extractComponentOptions(MyComponent)

const props = extractComponentProps(MyComponent)

// props
expectType<ExpectedProps['a']>(props.a)
Expand All @@ -197,55 +199,30 @@ describe('object props', () => {
expectType<ExpectedProps['validated']>(props.validated)
expectType<ExpectedProps['object']>(props.object)

// raw bindings
expectType<Number>(rawBindings.setupA)
expectType<Ref<Number>>(rawBindings.setupB)
expectType<Ref<Number>>(rawBindings.setupC.a)
expectType<Ref<Number> | undefined>(rawBindings.setupD)

// raw bindings props
expectType<ExpectedProps['a']>(rawBindings.setupProps.a)
expectType<ExpectedProps['b']>(rawBindings.setupProps.b)
expectType<ExpectedProps['e']>(rawBindings.setupProps.e)
expectType<ExpectedProps['bb']>(rawBindings.setupProps.bb)
expectType<ExpectedProps['bbb']>(rawBindings.setupProps.bbb)
expectType<ExpectedProps['cc']>(rawBindings.setupProps.cc)
expectType<ExpectedProps['dd']>(rawBindings.setupProps.dd)
expectType<ExpectedProps['ee']>(rawBindings.setupProps.ee)
expectType<ExpectedProps['ff']>(rawBindings.setupProps.ff)
expectType<ExpectedProps['ccc']>(rawBindings.setupProps.ccc)
expectType<ExpectedProps['ddd']>(rawBindings.setupProps.ddd)
expectType<ExpectedProps['eee']>(rawBindings.setupProps.eee)
expectType<ExpectedProps['fff']>(rawBindings.setupProps.fff)
expectType<ExpectedProps['hhh']>(rawBindings.setupProps.hhh)
expectType<ExpectedProps['ggg']>(rawBindings.setupProps.ggg)
expectType<ExpectedProps['ffff']>(rawBindings.setupProps.ffff)
expectType<ExpectedProps['validated']>(rawBindings.setupProps.validated)

// setup
expectType<Number>(setup.setupA)
expectType<Number>(setup.setupB)
expectType<Ref<Number>>(setup.setupC.a)
expectType<number | undefined>(setup.setupD)
expectType<number>(data.setupA)
expectType<number>(data.setupB)
expectType<Ref<number>>(data.setupC.a)
expectType<number | undefined>(data.setupD)

// raw bindings props
expectType<ExpectedProps['a']>(setup.setupProps.a)
expectType<ExpectedProps['b']>(setup.setupProps.b)
expectType<ExpectedProps['e']>(setup.setupProps.e)
expectType<ExpectedProps['bb']>(setup.setupProps.bb)
expectType<ExpectedProps['bbb']>(setup.setupProps.bbb)
expectType<ExpectedProps['cc']>(setup.setupProps.cc)
expectType<ExpectedProps['dd']>(setup.setupProps.dd)
expectType<ExpectedProps['ee']>(setup.setupProps.ee)
expectType<ExpectedProps['ff']>(setup.setupProps.ff)
expectType<ExpectedProps['ccc']>(setup.setupProps.ccc)
expectType<ExpectedProps['ddd']>(setup.setupProps.ddd)
expectType<ExpectedProps['eee']>(setup.setupProps.eee)
expectType<ExpectedProps['fff']>(setup.setupProps.fff)
expectType<ExpectedProps['hhh']>(setup.setupProps.hhh)
expectType<ExpectedProps['ggg']>(setup.setupProps.ggg)
expectType<ExpectedProps['ffff']>(setup.setupProps.ffff)
expectType<ExpectedProps['validated']>(setup.setupProps.validated)
expectType<ExpectedProps['a']>(data.setupProps.a)
expectType<ExpectedProps['b']>(data.setupProps.b)
expectType<ExpectedProps['e']>(data.setupProps.e)
expectType<ExpectedProps['bb']>(data.setupProps.bb)
expectType<ExpectedProps['bbb']>(data.setupProps.bbb)
expectType<ExpectedProps['cc']>(data.setupProps.cc)
expectType<ExpectedProps['dd']>(data.setupProps.dd)
expectType<ExpectedProps['ee']>(data.setupProps.ee)
expectType<ExpectedProps['ff']>(data.setupProps.ff)
expectType<ExpectedProps['ccc']>(data.setupProps.ccc)
expectType<ExpectedProps['ddd']>(data.setupProps.ddd)
expectType<ExpectedProps['eee']>(data.setupProps.eee)
expectType<ExpectedProps['fff']>(data.setupProps.fff)
expectType<ExpectedProps['hhh']>(data.setupProps.hhh)
expectType<ExpectedProps['ggg']>(data.setupProps.ggg)
expectType<ExpectedProps['ffff']>(data.setupProps.ffff)
expectType<ExpectedProps['validated']>(data.setupProps.validated)

// instance
const instance = new MyComponent()
Expand Down Expand Up @@ -331,8 +308,9 @@ describe('object props', () => {
},
} as const

const { props, rawBindings, setup } = extractComponentOptions(MyComponent)
const { data } = extractComponentOptions(MyComponent)

const props = extractComponentProps(MyComponent)
// props
expectType<ExpectedProps['a']>(props.a)
expectType<ExpectedProps['b']>(props.b)
Expand All @@ -349,15 +327,14 @@ describe('object props', () => {
expectType<ExpectedProps['fff']>(props.fff)
expectType<ExpectedProps['hhh']>(props.hhh)
expectType<ExpectedProps['ggg']>(props.ggg)
// expectType<ExpectedProps['ffff']>(props.ffff) // todo fix
expectType<ExpectedProps['ffff']>(props.ffff)
expectType<ExpectedProps['validated']>(props.validated)
expectType<ExpectedProps['object']>(props.object)

// rawBindings
expectType<Number>(rawBindings.setupA)

//setup
expectType<Number>(setup.setupA)
// data
expectType<number>(data.setupA)
// @ts-expect-error not any
expectType<string>(data.setupA)
})
})

Expand All @@ -372,15 +349,16 @@ describe('array props', () => {
},
})

const { props, rawBindings, setup } = extractComponentOptions(MyComponent)
const { props, data } = extractComponentOptions(MyComponent)

// @ts-expect-error props should be readonly
props.a = 1
expectType<any>(props.a)
expectType<any>(props.b)
// @ts-expect-error should not be any
expectType<string>(props.DoesNotExist)

expectType<number>(rawBindings.c)
expectType<number>(setup.c)
expectType<number>(data.c)
})

describe('options', () => {
Expand All @@ -393,17 +371,17 @@ describe('array props', () => {
},
}

const { props, rawBindings, setup } = extractComponentOptions(MyComponent)
const { data } = extractComponentOptions(MyComponent)

const props = extractComponentProps(MyComponent)

// @ts-expect-error props should be readonly
props.a = 1

// TODO infer the correct keys
// expectType<any>(props.a)
// expectType<any>(props.b)
expectType<any>(props.a)
expectType<any>(props.b)

expectType<number>(rawBindings.c)
expectType<number>(setup.c)
expectType<number>(data.c)
})
})

Expand All @@ -417,10 +395,9 @@ describe('no props', () => {
},
})

const { rawBindings, setup } = extractComponentOptions(MyComponent)
const { data } = extractComponentOptions(MyComponent)

expectType<number>(rawBindings.setupA)
expectType<number>(setup.setupA)
expectType<number>(data.setupA)

// instance
const instance = new MyComponent()
Expand All @@ -438,22 +415,20 @@ describe('no props', () => {
},
}

const { rawBindings, setup } = extractComponentOptions(MyComponent)
const { data } = extractComponentOptions(MyComponent)

expectType<number>(rawBindings.setupA)
expectType<number>(setup.setupA)
expectType<number>(data.setupA)
})
})

describe('functional', () => {
// TODO `props.foo` is `number|undefined`
// describe('defineComponent', () => {
// const MyComponent = defineComponent((props: { foo: number }) => {})
describe('defineComponent', () => {
const MyComponent = defineComponent((props: { foo: number }) => () => {})

// const { props } = extractComponentOptions(MyComponent)
const { props } = extractComponentOptions(MyComponent)

// expectType<number>(props.foo)
// })
expectType<number>(props.foo)
})

describe('function', () => {
const MyComponent = (props: { foo: number }) => props.foo
Expand Down Expand Up @@ -482,6 +457,10 @@ describe('functional', () => {
const { props, emits, slots } = extractComponentOptions(MyComponent)

expectType<Props>(props)
// should contain emits
expectType<EmitsToProps<Emits>>(props)
//@ts-expect-error cannot be any
expectType<boolean>(props)
expectType<Emits>(emits)
expectType<Slots>(slots)
})
Expand Down