Skip to content

Commit

Permalink
feat(types): update to Typescript 3.9 (#1106)
Browse files Browse the repository at this point in the history
  • Loading branch information
pikax committed Jun 9, 2020
1 parent 6cd97f0 commit 97dedeb
Show file tree
Hide file tree
Showing 17 changed files with 140 additions and 470 deletions.
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"lint": "prettier --write --parser typescript \"packages/**/*.ts?(x)\"",
"ls-lint": "ls-lint",
"test": "node scripts/build.js vue -f global -d && jest",
"test-dts": "node scripts/build.js shared reactivity runtime-core runtime-dom -dt -f esm-bundler && tsd",
"test-dts": "node scripts/build.js shared reactivity runtime-core runtime-dom -dt -f esm-bundler && tsc -p ./test-dts/tsconfig.json && tsc -p ./test-dts/tsconfig.build.json",
"release": "node scripts/release.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"dev-compiler": "npm-run-all --parallel \"dev template-explorer\" serve",
Expand Down Expand Up @@ -70,8 +70,7 @@
"semver": "^6.3.0",
"serve": "^11.3.0",
"ts-jest": "^25.2.1",
"tsd": "^0.11.0",
"typescript": "^3.8.3",
"typescript": "^3.9.3",
"yorkie": "^2.0.0"
}
}
8 changes: 4 additions & 4 deletions packages/runtime-core/src/componentOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ export interface ComponentOptionsBase<

// type-only differentiator to separate OptionWithoutProps from a constructor
// type returned by defineComponent() or FunctionalComponent
call?: never
call?: (this: unknown, ...args: unknown[]) => never
// type-only differentiators for built-in Vnode types
__isFragment?: never
__isTeleport?: never
Expand Down Expand Up @@ -197,9 +197,9 @@ export interface MethodOptions {
}

export type ExtractComputedReturns<T extends any> = {
[key in keyof T]: T[key] extends { get: Function }
? ReturnType<T[key]['get']>
: ReturnType<T[key]>
[key in keyof T]: T[key] extends { get: (...args: any[]) => infer TReturn }
? TReturn
: T[key] extends (...args: any[]) => infer TReturn ? TReturn : never
}

type WatchOptionItem =
Expand Down
1 change: 1 addition & 0 deletions packages/runtime-core/src/components/Suspense.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ function createSuspenseBoundary(
/* istanbul ignore if */
if (__DEV__ && !__TEST__ && !hasWarned) {
hasWarned = true
// @ts-ignore `console.info` cannot be null error
console[console.info ? 'info' : 'log'](
`<Suspense> is an experimental feature and its API will likely change.`
)
Expand Down
1 change: 1 addition & 0 deletions packages/runtime-dom/types/jsx.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,7 @@ declare global {
}
interface IntrinsicElements extends NativeElements {
// allow arbitrary elements
// @ts-ignore supress ts:2374 = Duplicate string index signature.
[name: string]: any
}
}
Expand Down
1 change: 1 addition & 0 deletions packages/vue/src/devCheck.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
if (__BROWSER__ && __DEV__) {
// @ts-ignore `console.info` cannot be null error
console[console.info ? 'info' : 'log'](
`You are running a development build of Vue.\n` +
`Make sure to use the production build (*.prod.js) when deploying for production.`
Expand Down
13 changes: 13 additions & 0 deletions test-dts/README.md
Original file line number Diff line number Diff line change
@@ -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.
5 changes: 3 additions & 2 deletions test-dts/componentTypeExtensions.test-d.ts
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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'))
}
}
Expand Down
31 changes: 23 additions & 8 deletions test-dts/defineComponent.test-d.tsx
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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`
Expand All @@ -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
Expand Down Expand Up @@ -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']} />)
})

Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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))
}
})
Expand All @@ -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'))
}
})
Expand Down
18 changes: 14 additions & 4 deletions test-dts/functionalComponent.test-d.tsx
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -18,24 +20,32 @@ 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'))
}

// assigning runtime options
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" />)
34 changes: 26 additions & 8 deletions test-dts/h.test-d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { expectError, expectAssignable } from 'tsd'
import {
describe,
h,
Expand All @@ -7,36 +6,48 @@ 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 }))
})

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

Expand All @@ -47,15 +58,19 @@ describe('h inference w/ Suspense', () => {
h(Suspense, null, {
default: () => 'foo'
})
// @ts-expect-error
expectError(h(Suspense, { onResolve: 1 }))
})

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

Expand Down Expand Up @@ -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 }))
})

Expand All @@ -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 }))
})

Expand All @@ -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 }))
})

Expand Down
4 changes: 4 additions & 0 deletions test-dts/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit 97dedeb

Please sign in to comment.