mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] types: make component generic types optional
In most cases, we just want Component<any, Env>. But since it was so annoying to have always the type Env, we actually used Component<any,any> everywhere. With this commit, the generic types have a default (and their order is swapped), so we can simply use Component in most cases, and Component<Props> when we want to type the props.
This commit is contained in:
+10
-10
@@ -46,7 +46,7 @@ interface MountOptions {
|
||||
* useful to typecheck and describe the internal keys used by Owl to manage the
|
||||
* component tree.
|
||||
*/
|
||||
interface Internal<T extends Env, Props> {
|
||||
interface Internal<T extends Env> {
|
||||
// each component has a unique id, useful mostly to handle parent/child
|
||||
// relationships
|
||||
readonly id: number;
|
||||
@@ -58,8 +58,8 @@ interface Internal<T extends Env, Props> {
|
||||
|
||||
// parent and children keys are obviously useful to setup the parent-children
|
||||
// relationship.
|
||||
parent: Component<T, any> | null;
|
||||
children: { [key: number]: Component<T, any> };
|
||||
parent: Component<any, T> | null;
|
||||
children: { [key: number]: Component<any, T> };
|
||||
// children mapping: from templateID to componentID. templateID identifies a
|
||||
// place in a template. The t-component directive needs it to be able to get
|
||||
// the component instance back whenever the template is rerendered.
|
||||
@@ -85,7 +85,7 @@ interface Internal<T extends Env, Props> {
|
||||
willStartCB: Function | null;
|
||||
willUpdatePropsCB: Function | null;
|
||||
classObj: { [key: string]: boolean } | null;
|
||||
refs: { [key: string]: Component<T, any> | HTMLElement | undefined } | null;
|
||||
refs: { [key: string]: Component<any, T> | HTMLElement | undefined } | null;
|
||||
}
|
||||
|
||||
export const portalSymbol = Symbol("portal"); // FIXME
|
||||
@@ -95,11 +95,11 @@ export const portalSymbol = Symbol("portal"); // FIXME
|
||||
//------------------------------------------------------------------------------
|
||||
let nextId = 1;
|
||||
|
||||
export class Component<T extends Env, Props extends {}> {
|
||||
readonly __owl__: Internal<Env, Props>;
|
||||
export class Component<Props extends {} = any, T extends Env = Env> {
|
||||
readonly __owl__: Internal<T>;
|
||||
static template?: string | null = null;
|
||||
static _template?: string | null = null;
|
||||
static current: Component<any, any> | null = null;
|
||||
static current: Component | null = null;
|
||||
static components = {};
|
||||
static props?: any;
|
||||
static defaultProps?: any;
|
||||
@@ -130,7 +130,7 @@ export class Component<T extends Env, Props extends {}> {
|
||||
* hand. Other components should be created automatically by the framework (with
|
||||
* the t-component directive in a template)
|
||||
*/
|
||||
constructor(parent?: Component<T, any> | null, props?: Props) {
|
||||
constructor(parent?: Component<any, T> | null, props?: Props) {
|
||||
Component.current = this;
|
||||
|
||||
let constr = this.constructor as any;
|
||||
@@ -441,7 +441,7 @@ export class Component<T extends Env, Props extends {}> {
|
||||
* Note that it does not call the __callWillUnmount method to avoid visiting
|
||||
* all children many times.
|
||||
*/
|
||||
__destroy(parent: Component<any, any> | null) {
|
||||
__destroy(parent: Component | null) {
|
||||
const __owl__ = this.__owl__;
|
||||
const isMounted = __owl__.isMounted;
|
||||
if (isMounted) {
|
||||
@@ -501,7 +501,7 @@ export class Component<T extends Env, Props extends {}> {
|
||||
* Private trigger method, allows to choose the component which triggered
|
||||
* the event in the first place
|
||||
*/
|
||||
__trigger(component: Component<any, any>, eventType: string, payload?: any) {
|
||||
__trigger(component: Component, eventType: string, payload?: any) {
|
||||
if (this.el) {
|
||||
const ev = new OwlEvent(component, eventType, {
|
||||
bubbles: true,
|
||||
|
||||
@@ -50,7 +50,7 @@ export class Fiber {
|
||||
|
||||
scope: any;
|
||||
|
||||
component: Component<any, any>;
|
||||
component: Component;
|
||||
vnode: VNode | null = null;
|
||||
|
||||
root: Fiber;
|
||||
@@ -61,7 +61,7 @@ export class Fiber {
|
||||
|
||||
error?: Error;
|
||||
|
||||
constructor(parent: Fiber | null, component: Component<any, any>, force, inserter) {
|
||||
constructor(parent: Fiber | null, component: Component, force: boolean, inserter) {
|
||||
this.component = component;
|
||||
this.force = force;
|
||||
this.inserter = inserter;
|
||||
|
||||
+2
-2
@@ -100,11 +100,11 @@ export class Context extends EventBus {
|
||||
* to context state changes. The `useContext` method returns the context state
|
||||
*/
|
||||
export function useContext(ctx: Context): any {
|
||||
const component: Component<any, any> = Component.current!;
|
||||
const component: Component = Component.current!;
|
||||
return useContextWithCB(ctx, component, component.render.bind(component));
|
||||
}
|
||||
|
||||
export function useContextWithCB(ctx: Context, component: Component<any, any>, method): any {
|
||||
export function useContextWithCB(ctx: Context, component: Component, method): any {
|
||||
const __owl__ = component.__owl__;
|
||||
const id = __owl__.id;
|
||||
const mapping = ctx.mapping;
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Component } from "../component/component";
|
||||
*/
|
||||
|
||||
export class OwlEvent<T> extends CustomEvent<T> {
|
||||
originalComponent: Component<any, any>;
|
||||
originalComponent: Component;
|
||||
constructor(component, eventType, options) {
|
||||
super(eventType, options);
|
||||
this.originalComponent = component;
|
||||
|
||||
+6
-6
@@ -22,7 +22,7 @@ import { Observer } from "./core/observer";
|
||||
* trigger a rerendering of the current component.
|
||||
*/
|
||||
export function useState<T>(state: T): T {
|
||||
const component: Component<any, any> = Component.current!;
|
||||
const component: Component = Component.current!;
|
||||
const __owl__ = component.__owl__;
|
||||
if (!__owl__.observer) {
|
||||
__owl__.observer = new Observer();
|
||||
@@ -37,7 +37,7 @@ export function useState<T>(state: T): T {
|
||||
function makeLifecycleHook(method: string, reverse: boolean = false) {
|
||||
if (reverse) {
|
||||
return function(cb) {
|
||||
const component: Component<any, any> = Component.current!;
|
||||
const component: Component = Component.current!;
|
||||
if (component.__owl__[method]) {
|
||||
const current = component.__owl__[method];
|
||||
component.__owl__[method] = function() {
|
||||
@@ -50,7 +50,7 @@ function makeLifecycleHook(method: string, reverse: boolean = false) {
|
||||
};
|
||||
} else {
|
||||
return function(cb) {
|
||||
const component: Component<any, any> = Component.current!;
|
||||
const component: Component = Component.current!;
|
||||
if (component.__owl__[method]) {
|
||||
const current = component.__owl__[method];
|
||||
component.__owl__[method] = function() {
|
||||
@@ -66,7 +66,7 @@ function makeLifecycleHook(method: string, reverse: boolean = false) {
|
||||
|
||||
function makeAsyncHook(method: string) {
|
||||
return function(cb) {
|
||||
const component: Component<any, any> = Component.current!;
|
||||
const component: Component = Component.current!;
|
||||
if (component.__owl__[method]) {
|
||||
const current = component.__owl__[method];
|
||||
component.__owl__[method] = function(...args) {
|
||||
@@ -96,7 +96,7 @@ export const onWillUpdateProps = makeAsyncHook("willUpdatePropsCB");
|
||||
*/
|
||||
interface Ref {
|
||||
el: HTMLElement | null;
|
||||
comp: Component<any, any> | null;
|
||||
comp: Component | null;
|
||||
}
|
||||
|
||||
export function useRef(name: string): Ref {
|
||||
@@ -111,7 +111,7 @@ export function useRef(name: string): Ref {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
get comp(): Component<any, any> | null {
|
||||
get comp(): Component | null {
|
||||
const val = __owl__.refs && __owl__.refs[name];
|
||||
return val instanceof Component ? val : null;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { xml } from "../tags";
|
||||
* from this coordination. This is the goal of the AsyncRoot component.
|
||||
*/
|
||||
|
||||
export class AsyncRoot extends Component<any, any> {
|
||||
export class AsyncRoot extends Component {
|
||||
static template = xml`<t t-slot="default"/>`;
|
||||
|
||||
async __updateProps(nextProps, parentFiber) {
|
||||
|
||||
+7
-3
@@ -18,7 +18,11 @@ import { useSubEnv } from "../hooks";
|
||||
* are re-triggered on an empty <portal> node located in the parent's DOM.
|
||||
*/
|
||||
|
||||
export class Portal extends Component<any, any> {
|
||||
interface Props {
|
||||
target: string;
|
||||
}
|
||||
|
||||
export class Portal extends Component<Props> {
|
||||
static template = xml`<portal><t t-slot="default"/></portal>`;
|
||||
static props = {
|
||||
target: {
|
||||
@@ -43,7 +47,7 @@ export class Portal extends Component<any, any> {
|
||||
// represents the element that is moved somewhere else
|
||||
portal: VNode | null = null;
|
||||
// the target where we will move `portal`
|
||||
target: HTMLElement | null = null;
|
||||
target: Element | null = null;
|
||||
|
||||
constructor(parent, props) {
|
||||
super(parent, props);
|
||||
@@ -158,7 +162,7 @@ export class Portal extends Component<any, any> {
|
||||
/**
|
||||
* Override to set the env
|
||||
*/
|
||||
__trigger(component: Component<any, any>, eventType: string, payload?: any) {
|
||||
__trigger(component: Component, eventType: string, payload?: any) {
|
||||
const env = this.env;
|
||||
this.env = this.parentEnv;
|
||||
super.__trigger(component, eventType, payload);
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ import { Destination, RouterEnv } from "./router";
|
||||
|
||||
type Props = Destination;
|
||||
|
||||
export class Link<Env extends RouterEnv> extends Component<Env, Props> {
|
||||
export class Link<Env extends RouterEnv> extends Component<Props, Env> {
|
||||
static template = xml`
|
||||
<a t-att-class="{'router-link-active': isActive }"
|
||||
t-att-href="href"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Component } from "../component/component";
|
||||
import { xml } from "../tags";
|
||||
|
||||
export class RouteComponent extends Component<any, {}> {
|
||||
export class RouteComponent extends Component {
|
||||
static template = xml`
|
||||
<t>
|
||||
<t
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ interface SelectorOptions {
|
||||
const isStrictEqual = (a, b) => a === b;
|
||||
|
||||
export function useStore(selector, options: SelectorOptions = {}): any {
|
||||
const component: Component<any, any> = Component.current!;
|
||||
const component: Component = Component.current!;
|
||||
const componentId = component.__owl__.id;
|
||||
const store = options.store || (component.env.store as Store);
|
||||
if (!(store instanceof Store)) {
|
||||
|
||||
Reference in New Issue
Block a user