diff --git a/src/runtime/validation.ts b/src/runtime/validation.ts index 36ed9f3e..78594b6b 100644 --- a/src/runtime/validation.ts +++ b/src/runtime/validation.ts @@ -1,16 +1,7 @@ import { OwlError } from "../common/owl_error"; import { toRaw } from "./reactivity"; -type BaseType = - | typeof String - | typeof Boolean - | typeof Number - | typeof Date - | typeof Object - | typeof Array - | typeof Function - | true - | "*"; +type BaseType = { new (...args: any[]): any } | true | "*"; interface TypeInfo { type?: TypeDescription; diff --git a/tests/components/__snapshots__/props_validation.test.ts.snap b/tests/components/__snapshots__/props_validation.test.ts.snap index 910f0e5b..56351a12 100644 --- a/tests/components/__snapshots__/props_validation.test.ts.snap +++ b/tests/components/__snapshots__/props_validation.test.ts.snap @@ -167,6 +167,45 @@ exports[`props validation can specify that additional props are allowed (object) }" `; +exports[`props validation can use custom class as type 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + const comp1 = app.createComponent(\`Child\`, true, false, false, [\\"customObj\\"]); + + return function template(ctx, node, key = \\"\\") { + const props1 = {customObj: ctx['customObj']}; + helpers.validateProps(\`Child\`, props1, this); + return comp1(props1, key + \`__1\`, node, this, null); + } +}" +`; + +exports[`props validation can use custom class as type 2`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + + return function template(ctx, node, key = \\"\\") { + return text(ctx['props'].customObj.val); + } +}" +`; + +exports[`props validation can use custom class as type: validation failure 1`] = ` +"function anonymous(app, bdom, helpers +) { + let { text, createBlock, list, multi, html, toggler, comment } = bdom; + const comp1 = app.createComponent(\`Child\`, true, false, false, [\\"customObj\\"]); + + return function template(ctx, node, key = \\"\\") { + const props1 = {customObj: ctx['customObj']}; + helpers.validateProps(\`Child\`, props1, this); + return comp1(props1, key + \`__1\`, node, this, null); + } +}" +`; + exports[`props validation can validate a prop with multiple types 1`] = ` "function anonymous(app, bdom, helpers ) { diff --git a/tests/components/props_validation.test.ts b/tests/components/props_validation.test.ts index f5f744b0..b1b8e81b 100644 --- a/tests/components/props_validation.test.ts +++ b/tests/components/props_validation.test.ts @@ -829,6 +829,52 @@ describe("props validation", () => { expect(error!).toBeDefined(); expect(error!.message).toBe("Invalid props for component 'Child': 'message' is missing"); }); + + test("can use custom class as type", async () => { + class CustomClass { + val = "hey"; + } + class Child extends Component { + static props = { customObj: CustomClass }; + static template = xml``; + } + + class Parent extends Component { + static components = { Child }; + static template = xml``; + customObj = new CustomClass(); + } + + const app = new App(Parent, { test: true }); + await app.mount(fixture); + expect(fixture.innerHTML).toBe("hey"); + }); + + test("can use custom class as type: validation failure", async () => { + class CustomClass {} + class Child extends Component { + static props = { customObj: CustomClass }; + static template = xml`
hey
`; + } + + class Parent extends Component { + static components = { Child }; + static template = xml``; + customObj = {}; + } + + const app = new App(Parent, { test: true }); + let error: OwlError | undefined; + const mountProm = app.mount(fixture).catch((e: Error) => (error = e)); + await expect(nextAppError(app)).resolves.toThrow( + "Invalid props for component 'Child': 'customObj' is not a customclass" + ); + await mountProm; + expect(error!).toBeDefined(); + expect(error!.message).toBe( + "Invalid props for component 'Child': 'customObj' is not a customclass" + ); + }); }); //------------------------------------------------------------------------------