Skip to content

Commit

Permalink
fix(lit-analyzer/no-incompatible-type-binding): exclude symbols when …
Browse files Browse the repository at this point in the history
…checking binding types. fix runem#207, fix runem#251, fix runem#316.
  • Loading branch information
SegaraRai committed Jul 27, 2024
1 parent b0e79a9 commit cc5809f
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,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);
Expand Down Expand Up @@ -82,6 +86,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
Expand Down
12 changes: 11 additions & 1 deletion packages/lit-analyzer/src/test/helpers/compile-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,17 @@ 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!),
...(includeLib
? [
"node_modules/typescript/lib/lib.dom.d.ts",
// We need this to enable `Symbol`.
// We cannot use "esnext" since it cannot be loaded by TS 4.8.4.
"node_modules/typescript/lib/lib.es2015.d.ts"
]
: [])
],
//rootNames: files.map(file => file.fileName!),
options: compilerOptions,
host: compilerHost
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,3 +293,39 @@ 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\`<div aria-expanded=\${userInput}></div>\`
`);

hasNoDiagnostics(t, diagnostics);
});

tsTest("Attribute binding: symbols are not treated as any type", t => {
const { diagnostics } = getDiagnostics(`
declare const value: "invalid" | unique symbol;
html\`<div aria-expanded=\${value}></div>\`
`);

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<T>(value: T | null | undefined): T | typeof nothing {
return value ?? nothing;
}
declare const value: boolean | null;
html\`<div aria-expanded=\${customIfDef(value)}></div>\`
`);

hasNoDiagnostics(t, diagnostics);
});

0 comments on commit cc5809f

Please sign in to comment.