microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.08k stars 12.49k forks source link

Can't use constructors to define custom elements (regression) #35951

Closed falsandtru closed 4 years ago

falsandtru commented 4 years ago

@sandersn Does IDL really intent this breaking change?

TypeScript Version: 3.7.x-dev.20200101

Search Terms:

Code

window.customElements.define('custom-tag', class extends HTMLElement { });

Expected behavior: pass Actual behavior: Argument of type 'typeof (Anonymous class)' is not assignable to parameter of type 'CustomElementConstructor'. Type 'typeof (Anonymous class)' provides no match for the signature '(): HTMLElement'.ts(2345) Playground Link:

Related Issues: https://github.com/whatwg/html/issues/5185

falsandtru commented 4 years ago

From whatwg/html#5185, this is a bug of IDL parser.

falsandtru commented 4 years ago

ping @sandersn

DanielRosenwasser commented 4 years ago

Isn't this fixed in the nightly?

http://www.typescriptlang.org/play/index.html?ts=Nightly#code/O4SwdgJg9sB0DGBXAzgFygWwKIBsCmGeYqysEeAZuHgBQDkSamAtKgIYDmdANAATw42yZLzwAPVEQgiAEgBUAsgBlcBIql4BvXgF8AlAG4gA

falsandtru commented 4 years ago

Well, @sandersn fixed this 3 days ago by https://github.com/microsoft/TSJS-lib-generator/pull/815.

As a comment for https://github.com/microsoft/TSJS-lib-generator/pull/815 and @sandersn, looks like the callback annotation of IDL doesn't clarify callable or constructable. We can't know a callback is callable or constructable without finding out if IsCallable or IsConstructor is used in the sequence. https://html.spec.whatwg.org/#custom-elements-api

sandersn commented 4 years ago

Thanks for the reference @falsandtru (and for testing that the fix works.)

SerkanSipahi commented 4 years ago

Hi @falsandtru @DanielRosenwasser @sandersn TypeScript Version: 3.8.3

It is not working properly!

Working:

customElements.define('some-template', class extends HTMLTemplateElement {}, {extends: 'template'});

Not working:

// Error: TS2345: Argument of type 'typeof PgHTMLTemplateElement' is not assignable to parameter of type 'CustomElementConstructor

class MyTemplate extends HTMLTemplateElement {}
customElements.define('some-template', MyTemplate, {extends: 'template'});

Workaround (see MyTemplate as any):


class MyTemplate extends HTMLTemplateElement {}
customElements.define('some-template', MyTemplate as any, {extends: 'template'});

Do i something wrong?

falsandtru commented 4 years ago

No error on the playground.

SerkanSipahi commented 4 years ago

Im using this tsconfig.json:

{
  "exclude": [
    "karma.conf.js",
    "build",
    "node_modules",
    "lib"
  ],
  "compilerOptions": {
    "types": [
      "jasmine",
      "node"
    ],
    /* Basic Options */
    "target": "ESNEXT",                       /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    "lib": ["es2015", "dom"],                 /* Specify library files to be included in the compilation. */
    "allowJs": true,                          /* Allow javascript files to be compiled. */
    "declaration": true,                      /* Generates corresponding '.d.ts' file. */
    "declarationMap": true,                   /* Generates a sourcemap for each corresponding '.d.ts' file. */
    "sourceMap": true,                        /* Generates corresponding '.map' file. */
    "outDir": "build",                        /* Redirect output structure to the directory. */
    "rootDir": "./",                          /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    "removeComments": true,                   /* Do not emit comments to output. */

    /* Strict Type-Checking Options */
    "strict": true,                           /* Enable all strict type-checking options. */
    "noImplicitAny": false,                   /* Raise error on expressions and declarations with an implied 'any' type. */
    "strictNullChecks": true,                 /* Enable strict null checks. */
    "strictFunctionTypes": true,              /* Enable strict checking of function types. */
    "strictBindCallApply": true,              /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
    "strictPropertyInitialization": true,     /* Enable strict checking of property initialization in classes. */
    "noImplicitThis": true,                   /* Raise error on 'this' expressions with an implied 'any' type. */
    "alwaysStrict": true,                     /* Parse in strict mode and emit "use strict" for each source file. */

    /* Additional Checks */
    "noUnusedLocals": false,                  /* Report errors on unused locals. */
    "noUnusedParameters": false,              /* Report errors on unused parameters. */
    "noImplicitReturns": true,                /* Report error when not all code paths in function return a value. */
    "noFallthroughCasesInSwitch": true,       /* Report errors for fallthrough cases in switch statement. */

    /* Module Resolution Options */
    "esModuleInterop": true,                  /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */

    /* Experimental Options */
    "experimentalDecorators": true,           /* Enables experimental support for ES7 decorators. */
    "emitDecoratorMetadata": true,            /* Enables experimental support for emitting type metadata for decorators. */

    /* Advanced Options */
    "resolveJsonModule": true,                /* Include modules imported with '.json' extension */
    "forceConsistentCasingInFileNames": true  /* Disallow inconsistently-cased references to the same file. */
  }
}
tomaswrobel commented 4 years ago

Workaround (see MyTemplate as any):

class MyTemplate extends HTMLTemplateElement {}
customElements.define('some-template', MyTemplate as any, {extends: 'template'});

Yes, this works perfectly.

SerkanSipahi commented 4 years ago

@tomas-wrobel do you had the same issue?

tomaswrobel commented 4 years ago

@SerkanSipahi

  1. it is “Did you have...?” grammatically correct
  2. Yes, I did. Converting to type “any” is good solution.
dmo-odoo commented 4 years ago

Facing the same error here on 3.8.3. Using as any works as expected but is only a workaround.

sdykae commented 4 years ago

still not working with 4.0.3 working with as any

jammerware commented 2 years ago

still not working with 4.0.3 working with as any

I know it's been like two years, but I'm having this problem on 4.8.4, and "as any" doesn't seem to work, assuming I understand the fix correctly. If anyone has time to look, I would so appreciate it:

https://jsfiddle.net/bensstein/q7Lupn61/9/