feat(types): update to Typescript 3.9 (#1106)

This commit is contained in:
Carlos Rodrigues
2020-06-09 15:17:42 +01:00
committed by GitHub
parent 6cd97f0ef2
commit 97dedebd80
17 changed files with 140 additions and 470 deletions

13
test-dts/README.md Normal file
View 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.

View File

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

View File

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

View File

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

View File

@@ -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
View File

@@ -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

View File

@@ -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

View 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
View File

@@ -0,0 +1,8 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"noEmit": true,
"declaration": true
},
"exclude": ["../packages/*/__tests__"]
}

View File

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

View File

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