feat(runtime-core): type and attr fallthrough support for emits option
This commit is contained in:
@@ -177,35 +177,35 @@ describe('with object props', () => {
|
||||
expectError(<MyComponent b="foo" dd={{ n: 'string' }} ddd={['foo']} />)
|
||||
})
|
||||
|
||||
describe('type inference w/ optional props declaration', () => {
|
||||
const MyComponent = defineComponent({
|
||||
setup(_props: { msg: string }) {
|
||||
return {
|
||||
a: 1
|
||||
}
|
||||
},
|
||||
render() {
|
||||
expectType<string>(this.$props.msg)
|
||||
// props should be readonly
|
||||
expectError((this.$props.msg = 'foo'))
|
||||
// should not expose on `this`
|
||||
expectError(this.msg)
|
||||
expectType<number>(this.a)
|
||||
return null
|
||||
}
|
||||
})
|
||||
// describe('type inference w/ optional props declaration', () => {
|
||||
// const MyComponent = defineComponent({
|
||||
// setup(_props: { msg: string }) {
|
||||
// return {
|
||||
// a: 1
|
||||
// }
|
||||
// },
|
||||
// render() {
|
||||
// expectType<string>(this.$props.msg)
|
||||
// // props should be readonly
|
||||
// expectError((this.$props.msg = 'foo'))
|
||||
// // should not expose on `this`
|
||||
// expectError(this.msg)
|
||||
// expectType<number>(this.a)
|
||||
// return null
|
||||
// }
|
||||
// })
|
||||
|
||||
expectType<JSX.Element>(<MyComponent msg="foo" />)
|
||||
expectError(<MyComponent />)
|
||||
expectError(<MyComponent msg={1} />)
|
||||
})
|
||||
// expectType<JSX.Element>(<MyComponent msg="foo" />)
|
||||
// expectError(<MyComponent />)
|
||||
// expectError(<MyComponent msg={1} />)
|
||||
// })
|
||||
|
||||
describe('type inference w/ direct setup function', () => {
|
||||
const MyComponent = defineComponent((_props: { msg: string }) => {})
|
||||
expectType<JSX.Element>(<MyComponent msg="foo" />)
|
||||
expectError(<MyComponent />)
|
||||
expectError(<MyComponent msg={1} />)
|
||||
})
|
||||
// describe('type inference w/ direct setup function', () => {
|
||||
// const MyComponent = defineComponent((_props: { msg: string }) => {})
|
||||
// expectType<JSX.Element>(<MyComponent msg="foo" />)
|
||||
// expectError(<MyComponent />)
|
||||
// expectError(<MyComponent msg={1} />)
|
||||
// })
|
||||
|
||||
describe('type inference w/ array props declaration', () => {
|
||||
defineComponent({
|
||||
@@ -320,3 +320,57 @@ describe('defineComponent', () => {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('emits', () => {
|
||||
// Note: for TSX inference, ideally we want to map emits to onXXX props,
|
||||
// but that requires type-level string constant concatenation as suggested in
|
||||
// https://github.com/Microsoft/TypeScript/issues/12754
|
||||
|
||||
// The workaround for TSX users is instead of using emits, declare onXXX props
|
||||
// and call them instead. Since `v-on:click` compiles to an `onClick` prop,
|
||||
// this would also support other users consuming the component in templates
|
||||
// with `v-on` listeners.
|
||||
|
||||
// with object emits
|
||||
defineComponent({
|
||||
emits: {
|
||||
click: (n: number) => typeof n === 'number',
|
||||
input: (b: string) => null
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
emit('click', 1)
|
||||
emit('input', 'foo')
|
||||
expectError(emit('nope'))
|
||||
expectError(emit('click'))
|
||||
expectError(emit('click', 'foo'))
|
||||
expectError(emit('input'))
|
||||
expectError(emit('input', 1))
|
||||
},
|
||||
created() {
|
||||
this.$emit('click', 1)
|
||||
this.$emit('input', 'foo')
|
||||
expectError(this.$emit('nope'))
|
||||
expectError(this.$emit('click'))
|
||||
expectError(this.$emit('click', 'foo'))
|
||||
expectError(this.$emit('input'))
|
||||
expectError(this.$emit('input', 1))
|
||||
}
|
||||
})
|
||||
|
||||
// with array emits
|
||||
defineComponent({
|
||||
emits: ['foo', 'bar'],
|
||||
setup(props, { emit }) {
|
||||
emit('foo')
|
||||
emit('foo', 123)
|
||||
emit('bar')
|
||||
expectError(emit('nope'))
|
||||
},
|
||||
created() {
|
||||
this.$emit('foo')
|
||||
this.$emit('foo', 123)
|
||||
this.$emit('bar')
|
||||
expectError(this.$emit('nope'))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
39
test-dts/functionalComponent.test-d.tsx
Normal file
39
test-dts/functionalComponent.test-d.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { expectError, expectType } from 'tsd'
|
||||
import { FunctionalComponent } from './index'
|
||||
|
||||
// simple function signature
|
||||
const Foo = (props: { foo: number }) => props.foo
|
||||
|
||||
// TSX
|
||||
expectType<JSX.Element>(<Foo foo={1} />)
|
||||
expectError(<Foo />)
|
||||
expectError(<Foo foo="bar" />)
|
||||
|
||||
// Explicit signature with props + emits
|
||||
const Bar: FunctionalComponent<
|
||||
{ foo: number },
|
||||
{ update: (value: number) => void }
|
||||
> = (props, { emit }) => {
|
||||
expectType<number>(props.foo)
|
||||
|
||||
emit('update', 123)
|
||||
expectError(emit('nope'))
|
||||
expectError(emit('update'))
|
||||
expectError(emit('update', 'nope'))
|
||||
}
|
||||
|
||||
// assigning runtime options
|
||||
Bar.props = {
|
||||
foo: Number
|
||||
}
|
||||
expectError((Bar.props = { foo: String }))
|
||||
|
||||
Bar.emits = {
|
||||
update: value => value > 1
|
||||
}
|
||||
expectError((Bar.emits = { baz: () => void 0 }))
|
||||
|
||||
// TSX
|
||||
expectType<JSX.Element>(<Bar foo={1} />)
|
||||
expectError(<Bar />)
|
||||
expectError(<Bar foo="bar" />)
|
||||
Reference in New Issue
Block a user