From 511ac0bd2fc5521f7de92cedd7c6aba2a7a92e17 Mon Sep 17 00:00:00 2001 From: Evan You Date: Thu, 4 Oct 2018 17:33:20 -0400 Subject: [PATCH] types: use stricter defaults for component data and props --- .../core/__tests__/attrsFallthrough.spec.ts | 14 ++++++++------ packages/core/src/component.ts | 9 ++++----- packages/core/src/componentProps.ts | 4 ++-- packages/core/src/optional/asyncComponent.ts | 3 ++- packages/core/src/optional/context.ts | 18 +++++++++++++----- 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/packages/core/__tests__/attrsFallthrough.spec.ts b/packages/core/__tests__/attrsFallthrough.spec.ts index 8f2c21fd..c10adb2b 100644 --- a/packages/core/__tests__/attrsFallthrough.spec.ts +++ b/packages/core/__tests__/attrsFallthrough.spec.ts @@ -6,7 +6,9 @@ describe('attribute fallthrough', () => { const nativeClick = jest.fn() const childUpdated = jest.fn() - class Hello extends Component { + class Hello extends Component<{ + count: number + }> { data() { return { count: 0 @@ -27,7 +29,7 @@ describe('attribute fallthrough', () => { } } - class Child extends Component { + class Child extends Component<{}, { foo: number }> { updated() { childUpdated() } @@ -73,7 +75,7 @@ describe('attribute fallthrough', () => { const nativeClick = jest.fn() const childUpdated = jest.fn() - class Hello extends Component { + class Hello extends Component<{ count: number }> { data() { return { count: 0 @@ -94,7 +96,7 @@ describe('attribute fallthrough', () => { } } - class Child extends Component { + class Child extends Component<{}, { foo: number }> { static options = { props: { foo: Number @@ -147,7 +149,7 @@ describe('attribute fallthrough', () => { const childUpdated = jest.fn() const grandChildUpdated = jest.fn() - class Hello extends Component { + class Hello extends Component<{ count: number }> { data() { return { count: 0 @@ -182,7 +184,7 @@ describe('attribute fallthrough', () => { } } - class GrandChild extends Component { + class GrandChild extends Component<{}, { foo: number }> { static options = { props: { foo: Number diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index b6500bf7..eb35be4d 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -13,17 +13,17 @@ import { ErrorTypes } from './errorHandling' type Flatten = { [K in keyof T]: T[K] } -export type RenderFunction

= ( +export type RenderFunction

= ( props: P, slots: Slots, attrs: Data ) => any export interface ComponentClass extends Flatten { - new (): D & P & MountedComponent + new (): D & P & MountedComponent } -export interface FunctionalComponent

extends RenderFunction

{ +export interface FunctionalComponent

extends RenderFunction

{ pure?: boolean props?: ComponentPropsOptions

inheritAttrs?: boolean @@ -33,8 +33,7 @@ export type ComponentType = ComponentClass | FunctionalComponent // this interface is merged with the class type // to represent a mounted component -export interface MountedComponent - extends InternalComponent { +export interface MountedComponent extends InternalComponent { $vnode: MountedVNode $data: D $props: P diff --git a/packages/core/src/componentProps.ts b/packages/core/src/componentProps.ts index d76b711a..0394fc69 100644 --- a/packages/core/src/componentProps.ts +++ b/packages/core/src/componentProps.ts @@ -37,11 +37,11 @@ export function updateProps(instance: MountedComponent, nextData: Data) { const rawProps = unwrap(props) for (const key in rawProps) { if (!nextProps.hasOwnProperty(key)) { - delete props[key] + delete (props as any)[key] } } for (const key in nextProps) { - props[key] = nextProps[key] + ;(props as any)[key] = nextProps[key] } if (nextAttrs) { const attrs = instance.$attrs diff --git a/packages/core/src/optional/asyncComponent.ts b/packages/core/src/optional/asyncComponent.ts index 752035a3..f84bbdb9 100644 --- a/packages/core/src/optional/asyncComponent.ts +++ b/packages/core/src/optional/asyncComponent.ts @@ -1,6 +1,7 @@ import { ChildrenFlags } from '../flags' import { createComponentVNode, Slots } from '../vdom' import { Component, ComponentType, ComponentClass } from '../component' +import { unwrap } from '@vue/observer' export interface AsyncComponentFactory { (): Promise @@ -92,7 +93,7 @@ export function createAsyncComponent( } else if (this.comp) { return createComponentVNode( this.comp, - props, + unwrap(props), slots, ChildrenFlags.STABLE_SLOTS ) diff --git a/packages/core/src/optional/context.ts b/packages/core/src/optional/context.ts index 0906d9d3..72093caf 100644 --- a/packages/core/src/optional/context.ts +++ b/packages/core/src/optional/context.ts @@ -4,15 +4,23 @@ import { Slots } from '../vdom' const contextStore = observable() as Record -export class Provide extends Component { +interface ProviderProps { + id: string | symbol + value: any +} + +export class Provide extends Component<{}, ProviderProps> { updateValue() { - contextStore[this.$props.id] = this.$props.value + // TS doesn't allow symbol as index :/ + // https://github.com/Microsoft/TypeScript/issues/24587 + contextStore[this.$props.id as string] = this.$props.value } created() { if (__DEV__) { - if (contextStore.hasOwnProperty(this.$props.id)) { + const { id } = this.$props + if (contextStore.hasOwnProperty(id)) { console.warn( - `A context provider with id ${this.$props.id} already exists.` + `A context provider with id ${id.toString()} already exists.` ) } this.$watch( @@ -31,7 +39,7 @@ export class Provide extends Component { beforeUpdate() { this.updateValue() } - render(props: any, slots: Slots) { + render(props: ProviderProps, slots: Slots) { return slots.default && slots.default() } }