fix(typescript): strict types should not throw errors

This commit is contained in:
Mostafa Sherif 2023-02-07 10:15:37 -05:00
parent 4d163568c2
commit c1d9f2b9a1
4 changed files with 47 additions and 45 deletions

View File

@ -23,7 +23,7 @@ const _getPath = (path: string[], node: t.Node): t.Node | undefined => {
}
if (t.isObjectExpression(node)) {
const [first, ...rest] = path;
const field = node.properties.find((p: t.ObjectProperty) => propKey(p) === first);
const field = (node.properties as t.ObjectProperty[]).find((p) => propKey(p) === first);
if (field) {
return _getPath(rest, (field as t.ObjectProperty).value);
}
@ -41,7 +41,7 @@ const _getPathProperties = (path: string[], node: t.Node): t.ObjectProperty[] |
}
if (t.isObjectExpression(node)) {
const [first, ...rest] = path;
const field = node.properties.find((p: t.ObjectProperty) => propKey(p) === first);
const field = (node.properties as t.ObjectProperty[]).find((p) => propKey(p) === first);
if (field) {
// FXIME handle spread etc.
if (rest.length === 0) return node.properties as t.ObjectProperty[];
@ -92,8 +92,8 @@ const _makeObjectExpression = (path: string[], value: t.Expression): t.Expressio
// eslint-disable-next-line @typescript-eslint/naming-convention
const _updateExportNode = (path: string[], expr: t.Expression, existing: t.ObjectExpression) => {
const [first, ...rest] = path;
const existingField = existing.properties.find(
(p: t.ObjectProperty) => propKey(p) === first
const existingField = (existing.properties as t.ObjectProperty[]).find(
(p) => propKey(p) === first
) as t.ObjectProperty;
if (!existingField) {
existing.properties.push(
@ -113,7 +113,7 @@ export class ConfigFile {
_exports: Record<string, t.Expression> = {};
_exportsObject: t.ObjectExpression;
_exportsObject: t.ObjectExpression | undefined;
_quotes: 'single' | 'double' | undefined;
@ -144,12 +144,12 @@ export class ConfigFile {
if (t.isObjectExpression(decl)) {
self._exportsObject = decl;
decl.properties.forEach((p: t.ObjectProperty) => {
(decl.properties as t.ObjectProperty[]).forEach((p) => {
const exportName = propKey(p);
if (exportName) {
let exportVal = p.value;
if (t.isIdentifier(exportVal)) {
exportVal = _findVarInitialization(exportVal.name, parent as t.Program);
exportVal = _findVarInitialization(exportVal.name, parent as t.Program) as any;
}
self._exports[exportName] = exportVal as t.Expression;
}
@ -166,9 +166,9 @@ export class ConfigFile {
node.declaration.declarations.forEach((decl) => {
if (t.isVariableDeclarator(decl) && t.isIdentifier(decl.id)) {
const { name: exportName } = decl.id;
let exportVal = decl.init;
let exportVal = decl.init as t.Expression;
if (t.isIdentifier(exportVal)) {
exportVal = _findVarInitialization(exportVal.name, parent as t.Program);
exportVal = _findVarInitialization(exportVal.name, parent as t.Program) as any;
}
self._exports[exportName] = exportVal;
}
@ -191,16 +191,19 @@ export class ConfigFile {
) {
let exportObject = right;
if (t.isIdentifier(right)) {
exportObject = _findVarInitialization(right.name, parent as t.Program);
exportObject = _findVarInitialization(right.name, parent as t.Program) as any;
}
if (t.isObjectExpression(exportObject)) {
self._exportsObject = exportObject;
exportObject.properties.forEach((p: t.ObjectProperty) => {
(exportObject.properties as t.ObjectProperty[]).forEach((p) => {
const exportName = propKey(p);
if (exportName) {
let exportVal = p.value;
let exportVal = p.value as t.Expression;
if (t.isIdentifier(exportVal)) {
exportVal = _findVarInitialization(exportVal.name, parent as t.Program);
exportVal = _findVarInitialization(
exportVal.name,
parent as t.Program
) as any;
}
self._exports[exportName] = exportVal as t.Expression;
}
@ -302,7 +305,7 @@ export class ConfigFile {
const pathNames: string[] = [];
if (t.isArrayExpression(node)) {
node.elements.forEach((element) => {
(node.elements as t.Expression[]).forEach((element) => {
pathNames.push(this._getPresetValue(element, 'name'));
});
}
@ -405,7 +408,7 @@ export class ConfigFile {
const properties = this.getFieldProperties(path) as t.ObjectProperty[];
if (properties) {
const lastPath = path.at(-1);
const lastPath = path.at(-1) as string;
removeProperty(properties, lastPath);
}
}

View File

@ -40,8 +40,8 @@ function parseTags(prop: t.Node) {
}
const findVarInitialization = (identifier: string, program: t.Program) => {
let init: t.Expression = null;
let declarations: t.VariableDeclarator[] = null;
let init: t.Expression = null as any;
let declarations: t.VariableDeclarator[] = null as any;
program.body.find((node: t.Node) => {
if (t.isVariableDeclaration(node)) {
declarations = node.declarations;
@ -57,7 +57,7 @@ const findVarInitialization = (identifier: string, program: t.Program) => {
t.isIdentifier(decl.id) &&
decl.id.name === identifier
) {
init = decl.init;
init = decl.init as t.Expression;
return true; // stop looking
}
return false;
@ -68,7 +68,7 @@ const findVarInitialization = (identifier: string, program: t.Program) => {
};
const formatLocation = (node: t.Node, fileName?: string) => {
const { line, column } = node.loc.start;
const { line, column } = node.loc?.start || {};
return `${fileName || ''} (line ${line}, col ${column})`.trim();
};
@ -108,7 +108,7 @@ const isArgsStory = (init: t.Node, parent: t.Node, csf: CsfFile) => {
const parseExportsOrder = (init: t.Expression) => {
if (t.isArrayExpression(init)) {
return init.elements.map((item: t.Expression) => {
return (init.elements as t.Expression[]).map((item) => {
if (t.isStringLiteral(item)) {
return item.value;
}
@ -147,7 +147,6 @@ export interface StaticMeta
ComponentAnnotations,
'id' | 'title' | 'includeStories' | 'excludeStories' | 'tags'
> {
[key: string]: string | string[] | RegExp;
component?: string;
}
@ -186,7 +185,7 @@ export class CsfFile {
constructor(ast: t.File, { fileName, makeTitle }: CsfOptions) {
this._ast = ast;
this._fileName = fileName;
this._fileName = fileName as string;
this.imports = [];
this._makeTitle = makeTitle;
}
@ -205,14 +204,14 @@ export class CsfFile {
_parseMeta(declaration: t.ObjectExpression, program: t.Program) {
const meta: StaticMeta = {};
declaration.properties.forEach((p: t.ObjectProperty) => {
(declaration.properties as t.ObjectProperty[]).forEach((p) => {
if (t.isIdentifier(p.key)) {
this._metaAnnotations[p.key.name] = p.value;
if (p.key.name === 'title') {
meta.title = this._parseTitle(p.value);
} else if (['includeStories', 'excludeStories'].includes(p.key.name)) {
meta[p.key.name] = parseIncludeExclude(p.value);
(meta as any)[p.key.name] = parseIncludeExclude(p.value);
} else if (p.key.name === 'component') {
const { code } = generate.default(p.value, {});
meta.component = code;
@ -236,7 +235,7 @@ export class CsfFile {
getStoryExport(key: string) {
let node = this._storyExports[key] as t.Node;
node = t.isVariableDeclarator(node) ? node.init : node;
node = t.isVariableDeclarator(node) ? (node.init as t.Node) : node;
if (t.isCallExpression(node)) {
const { callee, arguments: bindArguments } = node;
if (
@ -262,7 +261,7 @@ export class CsfFile {
traverse.default(this._ast, {
ExportDefaultDeclaration: {
enter({ node, parent }) {
let metaNode: t.ObjectExpression;
let metaNode: t.ObjectExpression | undefined;
const isVariableReference = t.isIdentifier(node.declaration) && t.isProgram(parent);
let decl;
if (isVariableReference) {
@ -277,9 +276,9 @@ export class CsfFile {
t.isVariableDeclaration(topLevelNode) &&
topLevelNode.declarations.find(isVariableDeclarator)
);
decl = (self._metaStatement as t.VariableDeclaration).declarations.find(
decl = ((self?._metaStatement as t.VariableDeclaration)?.declarations || []).find(
isVariableDeclarator
).init;
)?.init;
} else {
self._metaStatement = node;
decl = node.declaration;
@ -316,7 +315,7 @@ export class CsfFile {
if (t.isIdentifier(decl.id)) {
const { name: exportName } = decl.id;
if (exportName === '__namedExportsOrder' && t.isVariableDeclarator(decl)) {
self._namedExportsOrder = parseExportsOrder(decl.init);
self._namedExportsOrder = parseExportsOrder(decl.init as t.Expression);
return;
}
self._storyExports[exportName] = decl;
@ -334,7 +333,7 @@ export class CsfFile {
// eslint-disable-next-line @typescript-eslint/naming-convention
let __isArgsStory = true; // assume default render is an args story
// CSF3 object export
decl.init.properties.forEach((p: t.ObjectProperty) => {
(decl.init.properties as t.ObjectProperty[]).forEach((p) => {
if (t.isIdentifier(p.key)) {
if (p.key.name === 'render') {
__isArgsStory = isArgsStory(p.value as t.Expression, parent, self);
@ -354,7 +353,7 @@ export class CsfFile {
parameters = {
// __id: toId(self._meta.title, name),
// FIXME: Template.bind({});
__isArgsStory: isArgsStory(fn, parent, self),
__isArgsStory: isArgsStory(fn as t.Node, parent, self),
};
}
self._stories[exportName] = {
@ -370,7 +369,7 @@ export class CsfFile {
if (t.isExportSpecifier(specifier) && t.isIdentifier(specifier.exported)) {
const { name: exportName } = specifier.exported;
if (exportName === 'default') {
let metaNode: t.ObjectExpression;
let metaNode: t.ObjectExpression | undefined;
const decl = t.isProgram(parent)
? findVarInitialization(specifier.local.name, parent)
: specifier.local;
@ -418,7 +417,7 @@ export class CsfFile {
if (self._storyAnnotations[exportName]) {
if (annotationKey === 'story' && t.isObjectExpression(annotationValue)) {
annotationValue.properties.forEach((prop: t.ObjectProperty) => {
(annotationValue.properties as t.ObjectProperty[]).forEach((prop) => {
if (t.isIdentifier(prop.key)) {
self._storyAnnotations[exportName][prop.key.name] = prop.value;
}
@ -475,13 +474,13 @@ export class CsfFile {
// default export can come at any point in the file, so we do this post processing last
const entries = Object.entries(self._stories);
self._meta.title = this._makeTitle(self._meta.title);
self._meta.title = this._makeTitle(self._meta?.title as string);
if (self._metaAnnotations.play) {
self._meta.tags = [...(self._meta.tags || []), 'play-fn'];
}
self._stories = entries.reduce((acc, [key, story]) => {
if (isExportStory(key, self._meta)) {
const id = toId(self._meta.id || self._meta.title, storyNameFromExport(key));
if (isExportStory(key, self._meta as StaticMeta)) {
const id = toId((self._meta?.id || self._meta?.title) as string, storyNameFromExport(key));
const parameters: Record<string, any> = { ...story.parameters, __id: id };
const { includeStories } = self._meta || {};
if (
@ -506,7 +505,7 @@ export class CsfFile {
}, {} as Record<string, StaticStory>);
Object.keys(self._storyExports).forEach((key) => {
if (!isExportStory(key, self._meta)) {
if (!isExportStory(key, self._meta as StaticMeta)) {
delete self._storyExports[key];
delete self._storyAnnotations[key];
}
@ -557,5 +556,5 @@ export const readCsf = async (fileName: string, options: CsfOptions) => {
export const writeCsf = async (csf: CsfFile, fileName?: string) => {
const fname = fileName || csf._fileName;
if (!fname) throw new Error('Please specify a fileName for writeCsf');
await fs.writeFile(fileName, await formatCsf(csf));
await fs.writeFile(fileName as string, await formatCsf(csf));
};

View File

@ -135,7 +135,7 @@ export const enrichCsf = (csf: CsfFile, options?: EnrichCsfOptions) => {
export const extractSource = (node: t.Node) => {
const src = t.isVariableDeclarator(node) ? node.init : node;
const { code } = generate.default(src, {});
const { code } = generate.default(src as t.Node, {});
return code;
};

View File

@ -9,8 +9,8 @@ import { babelParse } from './babelParse';
const logger = console;
const getValue = (obj: t.ObjectExpression, key: string) => {
let value: t.Expression;
obj.properties.forEach((p: t.ObjectProperty) => {
let value: t.Expression | undefined;
(obj.properties as t.ObjectProperty[]).forEach((p) => {
if (t.isIdentifier(p.key) && p.key.name === key) {
value = p.value as t.Expression;
}
@ -20,12 +20,12 @@ const getValue = (obj: t.ObjectExpression, key: string) => {
const parseValue = (expr: t.Expression): any => {
if (t.isArrayExpression(expr)) {
return expr.elements.map((o: t.Expression) => {
return (expr.elements as t.Expression[]).map((o) => {
return parseValue(o);
});
}
if (t.isObjectExpression(expr)) {
return expr.properties.reduce((acc, p: t.ObjectProperty) => {
return (expr.properties as t.ObjectProperty[]).reduce((acc, p) => {
if (t.isIdentifier(p.key)) {
acc[p.key.name] = parseValue(p.value as t.Expression);
}
@ -60,7 +60,7 @@ const unsupported = (unexpectedVar: string, isError: boolean) => {
};
export const getStorySortParameter = (previewCode: string) => {
let storySort: t.Expression;
let storySort: t.Expression | undefined;
const ast = babelParse(previewCode);
traverse.default(ast, {
ExportNamedDeclaration: {
@ -109,7 +109,7 @@ export const getStorySortParameter = (previewCode: string) => {
if (t.isFunctionExpression(storySort)) {
const { code: sortCode } = generate.default(storySort, {});
const functionName = storySort.id.name;
const functionName = storySort.id?.name;
// Wrap the function within an arrow function, call it, and return
const wrapper = `(a, b) => {
${sortCode};