feat(runtime-core): type and attr fallthrough support for emits option

This commit is contained in:
Evan You
2020-04-03 12:05:52 -04:00
parent c409d4f297
commit bf473a64ea
9 changed files with 350 additions and 96 deletions

View File

@@ -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'))
}
})
})

View 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" />)