diff --git a/packages/lit-analyzer/src/lib/rules/util/type/extract-binding-types.ts b/packages/lit-analyzer/src/lib/rules/util/type/extract-binding-types.ts index ec9b7fb3..de631aa0 100644 --- a/packages/lit-analyzer/src/lib/rules/util/type/extract-binding-types.ts +++ b/packages/lit-analyzer/src/lib/rules/util/type/extract-binding-types.ts @@ -44,6 +44,10 @@ export function extractBindingTypes(assignment: HtmlNodeAttrAssignment, context: typeB = directiveType; } + // Handle `nothing` and `noChange` symbols + // Since it's not possible to check the details of a symbol due to various restrictions (it's treated as a `unique symbol` or `Symbol()`), all symbols are excluded. + typeB = excludeSymbolsFromUnion(typeB); + // Cache the result const result = { typeA, typeB }; cache.set(assignment, result); @@ -76,6 +80,17 @@ export function inferTypeFromAssignment(assignment: HtmlNodeAttrAssignment, chec } } +function excludeSymbolsFromUnion(type: SimpleType): SimpleType { + if (type.kind !== "UNION") { + return type; + } + + return { + ...type, + types: type.types.filter(t => t.kind !== "ES_SYMBOL" && t.kind !== "ES_SYMBOL_UNIQUE") + }; +} + /** * Relax the type so that for example "string literal" become "string" and "function" become "any" * This is used for javascript files to provide type checking with Typescript type inferring diff --git a/packages/lit-analyzer/src/test/helpers/compile-files.ts b/packages/lit-analyzer/src/test/helpers/compile-files.ts index 4b600102..98d1ee2b 100644 --- a/packages/lit-analyzer/src/test/helpers/compile-files.ts +++ b/packages/lit-analyzer/src/test/helpers/compile-files.ts @@ -106,8 +106,7 @@ export function compileFiles(inputFiles: TestFile[] | TestFile = []): { program: const program = ts.createProgram({ //rootNames: [...files.map(file => file.fileName!), "node_modules/typescript/lib/lib.dom.d.ts"], - rootNames: [...files.map(file => file.fileName!), ...(includeLib ? ["node_modules/typescript/lib/lib.dom.d.ts"] : [])], - //rootNames: files.map(file => file.fileName!), + rootNames: [...files.map(file => file.fileName!), ...(includeLib ? ["node_modules/typescript/lib/lib.dom.d.ts"] : [])], //rootNames: files.map(file => file.fileName!), options: compilerOptions, host: compilerHost }); diff --git a/packages/lit-analyzer/src/test/rules/no-incompatible-type-binding.ts b/packages/lit-analyzer/src/test/rules/no-incompatible-type-binding.ts index c7cc6226..30789bde 100644 --- a/packages/lit-analyzer/src/test/rules/no-incompatible-type-binding.ts +++ b/packages/lit-analyzer/src/test/rules/no-incompatible-type-binding.ts @@ -293,3 +293,34 @@ tsTest("Attribute binding: the target attribute is correctly type checked when g hasNoDiagnostics(t, diagnostics); }); + +tsTest("Attribute binding: any symbols are ignored on type checking", t => { + const { diagnostics } = getDiagnostics(` +declare const value: boolean | unique symbol; +html\`
\` + `); + + hasNoDiagnostics(t, diagnostics); +}); + +tsTest("Attribute binding: symbols are not treated as any type", t => { + const { diagnostics } = getDiagnostics(` +declare const value: "invalid" | unique symbol; +html\`\` + `); + + hasDiagnostic(t, diagnostics, "no-incompatible-type-binding"); +}); + +tsTest("Attribute binding: lit's nothing is ignored on type checking when returned by a function", t => { + const { diagnostics } = getDiagnostics(` +declare const nothing: unique symbol; +function customIfDef