From f5866b0d5a93663d9f9f4f827a9b0512539ede08 Mon Sep 17 00:00:00 2001 From: Declan Warn Date: Tue, 25 May 2021 17:09:13 +1000 Subject: [PATCH] Add typescript support for quoted keys in types (#188) * Add typescript support for quoted keys in types * docs(changeset): Allow proper conversion of keys in TypeScript types that are quoted. * Fix test * Better test, more reflective of use case * Clearer changeset message * Add test for type Co-authored-by: Declan Warn --- .changeset/seven-laws-deliver.md | 5 ++++ .../converters-typescript.test.js | 30 +++++++++++++++++++ packages/extract-react-types/src/converter.js | 28 +++++++++++++---- stories/TypeScriptComponent.tsx | 2 ++ 4 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 .changeset/seven-laws-deliver.md diff --git a/.changeset/seven-laws-deliver.md b/.changeset/seven-laws-deliver.md new file mode 100644 index 00000000..89032f55 --- /dev/null +++ b/.changeset/seven-laws-deliver.md @@ -0,0 +1,5 @@ +--- +'extract-react-types': patch +--- + +Adds support for string type keys in TypeScript. diff --git a/packages/extract-react-types/converters-typescript.test.js b/packages/extract-react-types/converters-typescript.test.js index c22aa77c..5b609626 100644 --- a/packages/extract-react-types/converters-typescript.test.js +++ b/packages/extract-react-types/converters-typescript.test.js @@ -690,3 +690,33 @@ cases( }, TESTS ); + +test('Typescript interface quoted property name is converted properly', () => { + const name = 'quoted'; + const code = stripIndent(` + interface Props { + /* Type comment for ${name} */ + '${name}': string; + } + + class Component extends React.Component {}`); + const typeSystem = 'typescript'; + const result = extractReactTypes(code, typeSystem, __filename); + + expect(result).toHaveProperty(['component', 'value', 'members', 0, 'key', 'name'], name); +}); + +test('Typescript type quoted property name is converted properly', () => { + const name = 'quoted'; + const code = stripIndent(` + type Props = { + /* Type comment for ${name} */ + '${name}': string; + } + + class Component extends React.Component {}`); + const typeSystem = 'typescript'; + const result = extractReactTypes(code, typeSystem, __filename); + + expect(result).toHaveProperty(['component', 'value', 'members', 0, 'key', 'name'], name); +}); diff --git a/packages/extract-react-types/src/converter.js b/packages/extract-react-types/src/converter.js index 9a9d3899..e67fdef7 100644 --- a/packages/extract-react-types/src/converter.js +++ b/packages/extract-react-types/src/converter.js @@ -535,12 +535,28 @@ converters.TSTypeLiteral = (path, context): K.Obj => ({ members: path.get('members').map(memberPath => convert(memberPath, context)) }); -converters.TSPropertySignature = (path, context): K.Property => ({ - kind: 'property', - optional: !!path.node.optional, - key: { kind: 'id', name: path.node.key.name }, - value: convert(path.get('typeAnnotation'), context) -}); +converters.TSPropertySignature = (path, context): K.Property => { + let key = { kind: 'id' }; + switch (path.node.key.type) { + case 'Identifier': + key.name = path.node.key.name; + break; + + case 'StringLiteral': + key.name = path.node.key.value; + break; + + default: + key.name = undefined; + } + + return { + kind: 'property', + optional: !!path.node.optional, + key, + value: convert(path.get('typeAnnotation'), context) + }; +}; converters.TSTypeAliasDeclaration = (path, context): K.Obj => convert(path.get('typeAnnotation'), context); diff --git a/stories/TypeScriptComponent.tsx b/stories/TypeScriptComponent.tsx index 408b1697..be27a19b 100644 --- a/stories/TypeScriptComponent.tsx +++ b/stories/TypeScriptComponent.tsx @@ -34,6 +34,8 @@ type TypeScriptComponentProps = { unknownProp: unknown; // This prop uses an unknown typescript keyword "keyof" and so will result in a bail-out unsupportedProp: keyof DummyInterface; + // This prop uses hyphens, so the type uses quotations around the key + 'quoted-prop': any; }; const TypeScriptComponent = (props: TypeScriptComponentProps) =>

Hello World

;