feat(types): update to Typescript 3.9 (#1106)
This commit is contained in:
13
test-dts/README.md
Normal file
13
test-dts/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Test-ts
|
||||
|
||||
Tests Typescript types to ensure the types remain as expected.
|
||||
|
||||
## Configuration
|
||||
|
||||
### tsconfig.json
|
||||
|
||||
Config used to test against the package source
|
||||
|
||||
### tsconfig.build.json
|
||||
|
||||
Replaces the `vue` and `@vue/*` dependencies with the built Typescript to ensure the published types are correct.
|
||||
@@ -1,5 +1,4 @@
|
||||
import { expectError, expectType } from 'tsd'
|
||||
import { defineComponent } from './index'
|
||||
import { defineComponent, expectError, expectType } from './index'
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
interface ComponentCustomOptions {
|
||||
@@ -20,9 +19,11 @@ export const Custom = defineComponent({
|
||||
|
||||
methods: {
|
||||
aMethod() {
|
||||
// @ts-expect-error
|
||||
expectError(this.notExisting)
|
||||
this.counter++
|
||||
this.state = 'running'
|
||||
// @ts-expect-error
|
||||
expectError((this.state = 'not valid'))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { expectError, expectType } from 'tsd'
|
||||
import {
|
||||
describe,
|
||||
defineComponent,
|
||||
PropType,
|
||||
ref,
|
||||
reactive,
|
||||
createApp
|
||||
createApp,
|
||||
expectError,
|
||||
expectType
|
||||
} from './index'
|
||||
|
||||
describe('with object props', () => {
|
||||
@@ -83,7 +84,7 @@ describe('with object props', () => {
|
||||
expectType<ExpectedProps['eee']>(props.eee)
|
||||
expectType<ExpectedProps['fff']>(props.fff)
|
||||
|
||||
// props should be readonly
|
||||
// @ts-expect-error props should be readonly
|
||||
expectError((props.a = 1))
|
||||
|
||||
// setup context
|
||||
@@ -112,7 +113,7 @@ describe('with object props', () => {
|
||||
expectType<ExpectedProps['eee']>(props.eee)
|
||||
expectType<ExpectedProps['fff']>(props.fff)
|
||||
|
||||
// props should be readonly
|
||||
// @ts-expect-error props should be readonly
|
||||
expectError((props.a = 1))
|
||||
|
||||
// should also expose declared props on `this`
|
||||
@@ -129,7 +130,7 @@ describe('with object props', () => {
|
||||
expectType<ExpectedProps['eee']>(this.eee)
|
||||
expectType<ExpectedProps['fff']>(this.fff)
|
||||
|
||||
// props on `this` should be readonly
|
||||
// @ts-expect-error props on `this` should be readonly
|
||||
expectError((this.a = 1))
|
||||
|
||||
// assert setup context unwrapping
|
||||
@@ -167,13 +168,14 @@ describe('with object props', () => {
|
||||
/>
|
||||
)
|
||||
|
||||
// missing required props
|
||||
// @ts-expect-error missing required props
|
||||
expectError(<MyComponent />)
|
||||
|
||||
// wrong prop types
|
||||
expectError(
|
||||
// @ts-expect-error wrong prop types
|
||||
<MyComponent a={'wrong type'} b="foo" dd={{ n: 1 }} ddd={['foo']} />
|
||||
)
|
||||
// @ts-expect-error
|
||||
expectError(<MyComponent b="foo" dd={{ n: 'string' }} ddd={['foo']} />)
|
||||
})
|
||||
|
||||
@@ -211,7 +213,7 @@ describe('type inference w/ array props declaration', () => {
|
||||
defineComponent({
|
||||
props: ['a', 'b'],
|
||||
setup(props) {
|
||||
// props should be readonly
|
||||
// @ts-expect-error props should be readonly
|
||||
expectError((props.a = 1))
|
||||
expectType<any>(props.a)
|
||||
expectType<any>(props.b)
|
||||
@@ -222,6 +224,7 @@ describe('type inference w/ array props declaration', () => {
|
||||
render() {
|
||||
expectType<any>(this.$props.a)
|
||||
expectType<any>(this.$props.b)
|
||||
// @ts-expect-error
|
||||
expectError((this.$props.a = 1))
|
||||
expectType<any>(this.a)
|
||||
expectType<any>(this.b)
|
||||
@@ -340,19 +343,29 @@ describe('emits', () => {
|
||||
setup(props, { emit }) {
|
||||
emit('click', 1)
|
||||
emit('input', 'foo')
|
||||
// @ts-expect-error
|
||||
expectError(emit('nope'))
|
||||
// @ts-expect-error
|
||||
expectError(emit('click'))
|
||||
// @ts-expect-error
|
||||
expectError(emit('click', 'foo'))
|
||||
// @ts-expect-error
|
||||
expectError(emit('input'))
|
||||
// @ts-expect-error
|
||||
expectError(emit('input', 1))
|
||||
},
|
||||
created() {
|
||||
this.$emit('click', 1)
|
||||
this.$emit('input', 'foo')
|
||||
// @ts-expect-error
|
||||
expectError(this.$emit('nope'))
|
||||
// @ts-expect-error
|
||||
expectError(this.$emit('click'))
|
||||
// @ts-expect-error
|
||||
expectError(this.$emit('click', 'foo'))
|
||||
// @ts-expect-error
|
||||
expectError(this.$emit('input'))
|
||||
// @ts-expect-error
|
||||
expectError(this.$emit('input', 1))
|
||||
}
|
||||
})
|
||||
@@ -364,12 +377,14 @@ describe('emits', () => {
|
||||
emit('foo')
|
||||
emit('foo', 123)
|
||||
emit('bar')
|
||||
// @ts-expect-error
|
||||
expectError(emit('nope'))
|
||||
},
|
||||
created() {
|
||||
this.$emit('foo')
|
||||
this.$emit('foo', 123)
|
||||
this.$emit('bar')
|
||||
// @ts-expect-error
|
||||
expectError(this.$emit('nope'))
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
import { expectError, expectType } from 'tsd'
|
||||
import { FunctionalComponent } from './index'
|
||||
import { FunctionalComponent, expectError, expectType } from './index'
|
||||
|
||||
// simple function signature
|
||||
const Foo = (props: { foo: number }) => props.foo
|
||||
|
||||
// TSX
|
||||
expectType<JSX.Element>(<Foo foo={1} />)
|
||||
// expectError(<Foo />) // tsd does not catch missing type errors
|
||||
// @ts-expect-error
|
||||
expectError(<Foo />)
|
||||
// @ts-expect-error
|
||||
expectError(<Foo foo="bar" />)
|
||||
// @ts-expect-error
|
||||
expectError(<Foo baz="bar" />)
|
||||
|
||||
// Explicit signature with props + emits
|
||||
@@ -18,8 +20,11 @@ const Bar: FunctionalComponent<
|
||||
expectType<number>(props.foo)
|
||||
|
||||
emit('update', 123)
|
||||
// @ts-expect-error
|
||||
expectError(emit('nope'))
|
||||
// @ts-expect-error
|
||||
expectError(emit('update'))
|
||||
// @ts-expect-error
|
||||
expectError(emit('update', 'nope'))
|
||||
}
|
||||
|
||||
@@ -27,15 +32,20 @@ const Bar: FunctionalComponent<
|
||||
Bar.props = {
|
||||
foo: Number
|
||||
}
|
||||
// @ts-expect-error
|
||||
expectError((Bar.props = { foo: String }))
|
||||
|
||||
Bar.emits = {
|
||||
update: value => value > 1
|
||||
}
|
||||
// @ts-expect-error
|
||||
expectError((Bar.emits = { baz: () => void 0 }))
|
||||
|
||||
// TSX
|
||||
expectType<JSX.Element>(<Bar foo={1} />)
|
||||
// expectError(<Foo />) // tsd does not catch missing type errors
|
||||
// @ts-expect-error
|
||||
expectError(<Foo />)
|
||||
// @ts-expect-error
|
||||
expectError(<Bar foo="bar" />)
|
||||
// @ts-expect-error
|
||||
expectError(<Foo baz="bar" />)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { expectError, expectAssignable } from 'tsd'
|
||||
import {
|
||||
describe,
|
||||
h,
|
||||
@@ -7,21 +6,28 @@ import {
|
||||
Fragment,
|
||||
Teleport,
|
||||
Suspense,
|
||||
Component
|
||||
Component,
|
||||
expectError,
|
||||
expectAssignable
|
||||
} from './index'
|
||||
|
||||
describe('h inference w/ element', () => {
|
||||
// key
|
||||
h('div', { key: 1 })
|
||||
h('div', { key: 'foo' })
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { key: [] }))
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { key: {} }))
|
||||
// ref
|
||||
h('div', { ref: 'foo' })
|
||||
h('div', { ref: ref(null) })
|
||||
h('div', { ref: el => {} })
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { ref: [] }))
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { ref: {} }))
|
||||
// @ts-expect-error
|
||||
expectError(h('div', { ref: 123 }))
|
||||
})
|
||||
|
||||
@@ -29,14 +35,19 @@ describe('h inference w/ Fragment', () => {
|
||||
// only accepts array children
|
||||
h(Fragment, ['hello'])
|
||||
h(Fragment, { key: 123 }, ['hello'])
|
||||
// @ts-expect-error
|
||||
expectError(h(Fragment, 'foo'))
|
||||
// @ts-expect-error
|
||||
expectError(h(Fragment, { key: 123 }, 'bar'))
|
||||
})
|
||||
|
||||
describe('h inference w/ Teleport', () => {
|
||||
h(Teleport, { to: '#foo' }, 'hello')
|
||||
// @ts-expect-error
|
||||
expectError(h(Teleport))
|
||||
// @ts-expect-error
|
||||
expectError(h(Teleport, {}))
|
||||
// @ts-expect-error
|
||||
expectError(h(Teleport, { to: '#foo' }))
|
||||
})
|
||||
|
||||
@@ -47,6 +58,7 @@ describe('h inference w/ Suspense', () => {
|
||||
h(Suspense, null, {
|
||||
default: () => 'foo'
|
||||
})
|
||||
// @ts-expect-error
|
||||
expectError(h(Suspense, { onResolve: 1 }))
|
||||
})
|
||||
|
||||
@@ -54,8 +66,11 @@ describe('h inference w/ functional component', () => {
|
||||
const Func = (_props: { foo: string; bar?: number }) => ''
|
||||
h(Func, { foo: 'hello' })
|
||||
h(Func, { foo: 'hello', bar: 123 })
|
||||
// @ts-expect-error
|
||||
expectError(h(Func, { foo: 123 }))
|
||||
// @ts-expect-error
|
||||
expectError(h(Func, {}))
|
||||
// @ts-expect-error
|
||||
expectError(h(Func, { bar: 123 }))
|
||||
})
|
||||
|
||||
@@ -85,10 +100,11 @@ describe('h inference w/ defineComponent', () => {
|
||||
h(Foo, { bar: 1, foo: 'ok' })
|
||||
// should allow extraneous props (attrs fallthrough)
|
||||
h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
|
||||
// should fail on missing required prop
|
||||
// @ts-expect-error should fail on missing required prop
|
||||
expectError(h(Foo, {}))
|
||||
// @ts-expect-error
|
||||
expectError(h(Foo, { foo: 'ok' }))
|
||||
// should fail on wrong type
|
||||
// @ts-expect-error should fail on wrong type
|
||||
expectError(h(Foo, { bar: 1, foo: 1 }))
|
||||
})
|
||||
|
||||
@@ -101,10 +117,11 @@ describe('h inference w/ defineComponent + optional props', () => {
|
||||
h(Foo, { bar: 1, foo: 'ok' })
|
||||
// should allow extraneous props (attrs fallthrough)
|
||||
h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
|
||||
// should fail on missing required prop
|
||||
// @ts-expect-error should fail on missing required prop
|
||||
expectError(h(Foo, {}))
|
||||
// @ts-expect-error
|
||||
expectError(h(Foo, { foo: 'ok' }))
|
||||
// should fail on wrong type
|
||||
// @ts-expect-error should fail on wrong type
|
||||
expectError(h(Foo, { bar: 1, foo: 1 }))
|
||||
})
|
||||
|
||||
@@ -115,10 +132,11 @@ describe('h inference w/ defineComponent + direct function', () => {
|
||||
h(Foo, { bar: 1, foo: 'ok' })
|
||||
// should allow extraneous props (attrs fallthrough)
|
||||
h(Foo, { bar: 1, foo: 'ok', class: 'extra' })
|
||||
// should fail on missing required prop
|
||||
// @ts-expect-error should fail on missing required prop
|
||||
expectError(h(Foo, {}))
|
||||
// @ts-expect-error
|
||||
expectError(h(Foo, { foo: 'ok' }))
|
||||
// should fail on wrong type
|
||||
// @ts-expect-error should fail on wrong type
|
||||
expectError(h(Foo, { bar: 1, foo: 1 }))
|
||||
})
|
||||
|
||||
|
||||
4
test-dts/index.d.ts
vendored
4
test-dts/index.d.ts
vendored
@@ -7,3 +7,7 @@
|
||||
export * from '@vue/runtime-dom'
|
||||
|
||||
export function describe(_name: string, _fn: () => void): void
|
||||
|
||||
export function expectType<T>(value: T): void
|
||||
export function expectError<T>(value: T): void
|
||||
export function expectAssignable<T, T2 extends T = T>(value: T2): void
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { expectType } from 'tsd'
|
||||
import { Ref, ref, isRef, unref, reactive } from './index'
|
||||
import { Ref, ref, isRef, unref, reactive, expectType } from './index'
|
||||
|
||||
function plainType(arg: number | Ref<number>) {
|
||||
// ref coercing
|
||||
|
||||
10
test-dts/tsconfig.build.json
Normal file
10
test-dts/tsconfig.build.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@vue/*": ["../packages/*/dist"],
|
||||
"vue": ["../packages/vue/dist"]
|
||||
}
|
||||
},
|
||||
"exclude": ["../packages/*/__tests__", "../packages/*/src"]
|
||||
}
|
||||
8
test-dts/tsconfig.json
Normal file
8
test-dts/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"noEmit": true,
|
||||
"declaration": true
|
||||
},
|
||||
"exclude": ["../packages/*/__tests__"]
|
||||
}
|
||||
@@ -1,13 +1,18 @@
|
||||
// TSX w/ defineComponent is tested in defineComponent.test-d.tsx
|
||||
|
||||
import { expectError, expectType } from 'tsd'
|
||||
import { KeepAlive, Suspense, Fragment, Teleport } from '@vue/runtime-dom'
|
||||
import {
|
||||
KeepAlive,
|
||||
Suspense,
|
||||
Fragment,
|
||||
Teleport,
|
||||
expectError,
|
||||
expectType
|
||||
} from './index'
|
||||
|
||||
expectType<JSX.Element>(<div />)
|
||||
expectType<JSX.Element>(<div id="foo" />)
|
||||
expectType<JSX.Element>(<input value="foo" />)
|
||||
|
||||
// unknown prop
|
||||
// @ts-expect-error unknown prop
|
||||
expectError(<div foo="bar" />)
|
||||
|
||||
// allow key/ref on arbitrary element
|
||||
@@ -29,16 +34,21 @@ expectType<JSX.Element>(<Fragment key="1" />)
|
||||
|
||||
expectType<JSX.Element>(<Teleport to="#foo" />)
|
||||
expectType<JSX.Element>(<Teleport to="#foo" key="1" />)
|
||||
|
||||
// @ts-expect-error
|
||||
expectError(<Teleport />)
|
||||
// @ts-expect-error
|
||||
expectError(<Teleport to={1} />)
|
||||
|
||||
// KeepAlive
|
||||
expectType<JSX.Element>(<KeepAlive include="foo" exclude={['a']} />)
|
||||
expectType<JSX.Element>(<KeepAlive key="1" />)
|
||||
// @ts-expect-error
|
||||
expectError(<KeepAlive include={123} />)
|
||||
|
||||
// Suspense
|
||||
expectType<JSX.Element>(<Suspense />)
|
||||
expectType<JSX.Element>(<Suspense key="1" />)
|
||||
expectType<JSX.Element>(<Suspense onResolve={() => {}} onRecede={() => {}} />)
|
||||
// @ts-expect-error
|
||||
expectError(<Suspense onResolve={123} />)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { ref, computed, watch } from './index'
|
||||
import { expectType } from 'tsd'
|
||||
import { ref, computed, watch, expectType } from './index'
|
||||
|
||||
const source = ref('foo')
|
||||
const source2 = computed(() => source.value)
|
||||
|
||||
Reference in New Issue
Block a user