diff --git a/.vscode/settings.json b/.vscode/settings.json index 50f76ba3..bb531a85 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -22,7 +22,6 @@ "rust", "scss", "text", - "typescriptreact", "yml" ] } diff --git a/packages/core/__tests__/attrsFallthrough.spec.ts b/packages/core/__tests__/attrsFallthrough.spec.ts index 41bf51bd..68740cc2 100644 --- a/packages/core/__tests__/attrsFallthrough.spec.ts +++ b/packages/core/__tests__/attrsFallthrough.spec.ts @@ -6,12 +6,8 @@ describe('attribute fallthrough', () => { const click = jest.fn() const childUpdated = jest.fn() - class Hello extends Component<{}, { count: number }> { - data() { - return { - count: 0 - } - } + class Hello extends Component { + count: number = 0 inc() { this.count++ click() @@ -27,7 +23,7 @@ describe('attribute fallthrough', () => { } } - class Child extends Component { + class Child extends Component<{ [key: string]: any }> { updated() { childUpdated() } @@ -73,19 +69,15 @@ describe('attribute fallthrough', () => { const click = jest.fn() const childUpdated = jest.fn() - class Hello extends Component<{}, { count: number }> { - data() { - return { - count: 0 - } - } + class Hello extends Component { + count = 0 inc() { this.count++ click() } render() { return h(Child, { - foo: 1, + foo: 123, id: 'test', class: 'c' + this.count, style: { color: this.count ? 'red' : 'green' }, @@ -94,7 +86,7 @@ describe('attribute fallthrough', () => { } } - class Child extends Component<{ foo: number }> { + class Child extends Component<{ [key: string]: any; foo: number }> { static props = { foo: Number } @@ -148,12 +140,8 @@ describe('attribute fallthrough', () => { const childUpdated = jest.fn() const grandChildUpdated = jest.fn() - class Hello extends Component<{}, { count: number }> { - data() { - return { - count: 0 - } - } + class Hello extends Component { + count = 0 inc() { this.count++ click() @@ -169,7 +157,7 @@ describe('attribute fallthrough', () => { } } - class Child extends Component { + class Child extends Component<{ [key: string]: any; foo: number }> { updated() { childUpdated() } @@ -178,7 +166,7 @@ describe('attribute fallthrough', () => { } } - class GrandChild extends Component<{ foo: number }> { + class GrandChild extends Component<{ [key: string]: any; foo: number }> { static props = { foo: Number } diff --git a/packages/core/src/component.ts b/packages/core/src/component.ts index 66fc4bb0..394bf984 100644 --- a/packages/core/src/component.ts +++ b/packages/core/src/component.ts @@ -13,9 +13,9 @@ import { nextTick } from '@vue/scheduler' import { ErrorTypes } from './errorHandling' import { initializeComponentInstance } from './componentUtils' -export interface ComponentClass extends ComponentClassOptions { +export interface ComponentClass
extends ComponentClassOptions { options?: ComponentOptions - new
(): MergedComponent
+ new
(props?: P): MergedComponent
} export type MergedComponent
= D & P & ComponentInstance
diff --git a/packages/core/src/componentOptions.ts b/packages/core/src/componentOptions.ts
index 690daab1..08cf83c8 100644
--- a/packages/core/src/componentOptions.ts
+++ b/packages/core/src/componentOptions.ts
@@ -1,18 +1,18 @@
-import { ComponentInstance } from './component'
+import { ComponentInstance, MergedComponent } from './component'
import { Slots } from './vdom'
export type Data = Record {
+ props?: ComponentPropsOptions
computed?: ComponentComputedOptions >
+ extends ComponentClassOptions {
+ data?(): D
render?: (this: This, props: Readonly, slots: Slots, attrs: Data) => any
// TODO other options
readonly [key: string]: any
diff --git a/packages/core/src/h.ts b/packages/core/src/h.ts
index 29c7d235..c461017d 100644
--- a/packages/core/src/h.ts
+++ b/packages/core/src/h.ts
@@ -2,7 +2,6 @@ import { ChildrenFlags } from './flags'
import {
ComponentClass,
FunctionalComponent,
- Component,
ComponentInstance
} from './component'
import { ComponentOptions } from './componentOptions'
@@ -14,7 +13,8 @@ import {
createFragment,
createPortal,
VNodeData,
- BuiltInProps
+ BuiltInProps,
+ Key
} from './vdom'
import { isObservable } from '@vue/observer'
import { warn } from './warning'
@@ -22,6 +22,14 @@ import { warn } from './warning'
export const Fragment = Symbol()
export const Portal = Symbol()
+type RawChildType = VNode | string | number | boolean | null | undefined
+
+export type RawSlots = {
+ [name: string]: () => RawChildrenType
+}
+
+export type RawChildrenType = RawChildType | RawChildType[]
+
export type ElementType =
| string
| FunctionalComponent
@@ -30,10 +38,6 @@ export type ElementType =
| typeof Fragment
| typeof Portal
-type RawChildType = VNode | string | number | boolean | null | undefined
-
-export type RawChildrenType = RawChildType | RawChildType[]
-
interface VNodeFactories {
c: typeof createComponentVNode
e: typeof createElementVNode
@@ -42,20 +46,60 @@ interface VNodeFactories {
p: typeof createPortal
}
-interface createElement {
+// This is used to differentiate the data object from
+// vnodes and arrays
+type Differ = { _isVNode?: never; [Symbol.iterator]?: never }
+
+type OptionsComponent =
+ | (ComponentOptions & { template: string })
+ | (ComponentOptions & { render: Function })
+
+interface createElement extends VNodeFactories {
// element
- (tag: string, data?: VNodeData, children?: any): VNode
+ (
+ tag: string,
+ // TODO support native element properties
+ data?: VNodeData & Differ | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ (tag: string, children?: RawChildrenType): VNode
+ // fragment
+ (
+ tag: typeof Fragment,
+ data?: ({ key?: Key } & Differ) | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ (tag: typeof Fragment, children?: RawChildrenType): VNode
+ // portal
+ (
+ tag: typeof Portal,
+ data?: ({ target: any } & BuiltInProps & Differ) | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ (tag: typeof Portal, children?: RawChildrenType): VNode
+ // object
+ (
+ tag: OptionsComponent ,
+ data?: (P & BuiltInProps & Differ) | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ (tag: OptionsComponent , children?: RawChildrenType): VNode
// functional
(
tag: FunctionalComponent ,
- data?: P & BuiltInProps | null,
- children?: any
+ data?: (P & BuiltInProps & Differ) | null,
+ children?: RawChildrenType | RawSlots
): VNode
- // stateful
+ (tag: FunctionalComponent , children?: RawChildrenType): VNode
+ // class
>(
tag: new () => T & { $props: P },
- data?: P & BuiltInProps | null,
- children?: any
+ data?: (P & BuiltInProps & Differ) | null,
+ children?: RawChildrenType | RawSlots
+ ): VNode
+ >(
+ tag: new () => T & { $props: P },
+ children?: RawChildrenType
): VNode
}
@@ -138,7 +182,7 @@ export const h = ((tag: ElementType, data?: any, children?: any): VNode => {
ref
)
}
-}) as createElement & VNodeFactories
+}) as createElement
h.c = createComponentVNode
h.e = createElementVNode
diff --git a/packages/core/src/optional/mixin.ts b/packages/core/src/optional/mixin.ts
index 902d9f2e..605075c0 100644
--- a/packages/core/src/optional/mixin.ts
+++ b/packages/core/src/optional/mixin.ts
@@ -1,16 +1,6 @@
-import { ComponentInstance, ComponentType } from '../component'
+import { ComponentInstance } from '../component'
import { ComponentOptions } from '../componentOptions'
-import { RawVNodeChildren, VNodeData } from '../vdom'
export interface Mixin extends ComponentOptions {}
export function applyMixins(Component: ComponentInstance, mixins: Mixin[]) {}
-
-export function h(tag: ComponentType | string, data: RawVNodeChildren): object
-export function h(
- tag: ComponentType | string,
- data: VNodeData,
- children: RawVNodeChildren
-): object {
- return {}
-}
diff --git a/packages/core/src/vdom.ts b/packages/core/src/vdom.ts
index f54fe3b1..811f7b26 100644
--- a/packages/core/src/vdom.ts
+++ b/packages/core/src/vdom.ts
@@ -6,7 +6,7 @@ import {
import { VNodeFlags, ChildrenFlags } from './flags'
import { createComponentClassFromOptions } from './componentUtils'
import { normalizeClass, normalizeStyle, handlersRE, EMPTY_OBJ } from './utils'
-import { ElementType, RawChildrenType } from './h'
+import { RawChildrenType, RawSlots } from './h'
// Vue core is platform agnostic, so we are not using Element for "DOM" nodes.
export interface RenderNode {
@@ -47,7 +47,9 @@ export interface BuiltInProps {
slots?: RawSlots | null
}
-export type VNodeData = Record