Skip to content

Commit

Permalink
feat(types): provide internal options for directly using user types i…
Browse files Browse the repository at this point in the history
…n language tools (#10801)
  • Loading branch information
yyx990803 authored Apr 27, 2024
1 parent 4cc9ca8 commit 75c8cf6
Show file tree
Hide file tree
Showing 10 changed files with 652 additions and 475 deletions.
145 changes: 144 additions & 1 deletion packages/dts-test/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
withKeys,
withModifiers,
} from 'vue'
import { type IsUnion, describe, expectType } from './utils'
import { type IsAny, type IsUnion, describe, expectType } from './utils'

describe('with object props', () => {
interface ExpectedProps {
Expand Down Expand Up @@ -1623,3 +1623,146 @@ declare const MyButton: DefineComponent<
{}
>
;<MyButton class="x" />

describe('__typeProps backdoor for union type for conditional props', () => {
interface CommonProps {
size?: 'xl' | 'l' | 'm' | 's' | 'xs'
}

type ConditionalProps =
| {
color?: 'normal' | 'primary' | 'secondary'
appearance?: 'normal' | 'outline' | 'text'
}
| {
color: 'white'
appearance: 'outline'
}

type Props = CommonProps & ConditionalProps

const Comp = defineComponent({
__typeProps: {} as Props,
})
// @ts-expect-error
;<Comp color="white" />
// @ts-expect-error
;<Comp color="white" appearance="normal" />
;<Comp color="white" appearance="outline" />

const c = new Comp()

// @ts-expect-error
c.$props = { color: 'white' }
// @ts-expect-error
c.$props = { color: 'white', appearance: 'text' }
c.$props = { color: 'white', appearance: 'outline' }
})

describe('__typeEmits backdoor, 3.3+ object syntax', () => {
type Emits = {
change: [id: number]
update: [value: string]
}

const Comp = defineComponent({
__typeEmits: {} as Emits,
mounted() {
this.$props.onChange?.(123)
// @ts-expect-error
this.$props.onChange?.('123')
this.$props.onUpdate?.('foo')
// @ts-expect-error
this.$props.onUpdate?.(123)

// @ts-expect-error
this.$emit('foo')

this.$emit('change', 123)
// @ts-expect-error
this.$emit('change', '123')

this.$emit('update', 'test')
// @ts-expect-error
this.$emit('update', 123)
},
})

;<Comp onChange={id => id.toFixed(2)} />
;<Comp onUpdate={id => id.toUpperCase()} />
// @ts-expect-error
;<Comp onChange={id => id.slice(1)} />
// @ts-expect-error
;<Comp onUpdate={id => id.toFixed(2)} />

const c = new Comp()
// @ts-expect-error
c.$emit('foo')

c.$emit('change', 123)
// @ts-expect-error
c.$emit('change', '123')

c.$emit('update', 'test')
// @ts-expect-error
c.$emit('update', 123)
})

describe('__typeEmits backdoor, call signature syntax', () => {
type Emits = {
(e: 'change', id: number): void
(e: 'update', value: string): void
}

const Comp = defineComponent({
__typeEmits: {} as Emits,
mounted() {
this.$props.onChange?.(123)
// @ts-expect-error
this.$props.onChange?.('123')
this.$props.onUpdate?.('foo')
// @ts-expect-error
this.$props.onUpdate?.(123)

// @ts-expect-error
this.$emit('foo')

this.$emit('change', 123)
// @ts-expect-error
this.$emit('change', '123')

this.$emit('update', 'test')
// @ts-expect-error
this.$emit('update', 123)
},
})

;<Comp onChange={id => id.toFixed(2)} />
;<Comp onUpdate={id => id.toUpperCase()} />
// @ts-expect-error
;<Comp onChange={id => id.slice(1)} />
// @ts-expect-error
;<Comp onUpdate={id => id.toFixed(2)} />

const c = new Comp()
// @ts-expect-error
c.$emit('foo')

c.$emit('change', 123)
// @ts-expect-error
c.$emit('change', '123')

c.$emit('update', 'test')
// @ts-expect-error
c.$emit('update', 123)
})

defineComponent({
props: {
foo: [String, null],
},
setup(props) {
expectType<IsAny<typeof props.foo>>(false)
expectType<string | null | undefined>(props.foo)
},
})
Loading

0 comments on commit 75c8cf6

Please sign in to comment.