diff --git a/README.md b/README.md index 77480f6..4df874c 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,12 @@ Transforms React code written in JavaScript to TypeScript. ```jsx class MyComponent extends React.Component { static propTypes = { - p: React.PropTypes.string.isRequired, - r: React.PropTypes.number + prop1: React.PropTypes.string.isRequired, + prop2: React.PropTypes.number } constructor() { super(); - this.state = { foo: 1, bar: 2 }; + this.state = { foo: 1, bar: 'str' }; } render() { return
{this.state.foo}, {this.state.bar}, {this.state.baz}
@@ -36,18 +36,18 @@ class MyComponent extends React.Component { **output** ```tsx -interface IMyComponentProps { - p: string; - r: number | undefined; +type MyComponentProps = { + prop1: string; + prop2: number | undefined; } -interface IMyComponentState { +type MyComponentState = { foo: number; bar: string; baz: number | undefined; } -class MyComponent extends React.Component { +class MyComponent extends React.Component { constructor() { super(); this.state = { foo: 1, bar: 'str' }; diff --git a/package.json b/package.json index 17d8438..710ed2a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-js-to-ts", - "version": "1.0.2", + "version": "1.1.0", "description": "Convert React code from JavaScript to TypeScript", "main": "dist/index.js", "scripts": { @@ -8,6 +8,7 @@ "test": "jest", "coverage": "jest --coverage", "posttest": "npm run lint", + "prelint": "npm run clean", "lint": "tslint --type-check --project tsconfig.json --format codeFrame --exclude test/**/*.tsx", "prepublish": "npm run build", "clean": "rm -rf dist", @@ -30,20 +31,20 @@ "license": "Apache-2.0", "dependencies": { "chalk": "^1.1.3", - "commander": "^2.9.0", + "commander": "^2.10.0", "glob": "^7.1.2", - "typescript": "^2.3.2" + "typescript": "^2.4.0" }, "devDependencies": { "@types/chalk": "^0.4.31", - "@types/commander": "^2.9.0", + "@types/commander": "^2.9.1", "@types/glob": "^5.0.30", - "@types/jest": "^19.2.3", - "@types/node": "^7.0.12", - "@types/react": "^15.0.21", - "jest": "^20.0.0", - "ts-jest": "^20.0.1", - "ts-node": "^3.0.2", + "@types/jest": "^20.0.2", + "@types/node": "^8.0.2", + "@types/react": "^15.0.31", + "jest": "^20.0.4", + "ts-jest": "^20.0.6", + "ts-node": "^3.1.0", "tslint": "^5.2.0" } } diff --git a/src/compiler.ts b/src/compiler.ts index 0762e58..6b5b0d9 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -28,8 +28,10 @@ export function compile(filePath: string, factoryFactories: TransformFactoryFact ======================= Diagnostics for ${filePath} ======================= `)); for (const diag of result.diagnostics) { - const pos = diag.file.getLineAndCharacterOfPosition(diag.start); - console.log(`(${pos.line}, ${pos.character}) ${diag.messageText}`) + if (diag.file && diag.start) { + const pos = diag.file.getLineAndCharacterOfPosition(diag.start); + console.log(`(${pos.line}, ${pos.character}) ${diag.messageText}`) + } } } diff --git a/src/helpers/index.ts b/src/helpers/index.ts index e80fc86..18c7315 100644 --- a/src/helpers/index.ts +++ b/src/helpers/index.ts @@ -43,22 +43,6 @@ export function isReactComponent(classDeclaration: ts.ClassDeclaration, typeChec return true; } -/** - * A temporary hack until ts allows creating type alias declaration nodes - * Creates a TypeAliasDeclaration - * @param name Name of type node - * @param type Type node - * @param sourceFile SourceFile for context - */ -export function createTypeDeclarationStatement(name: string, type: ts.TypeNode, sourceFile: ts.SourceFile) { - const printer = ts.createPrinter() - const typeString = printer.printNode(ts.EmitHint.Unspecified, type, sourceFile); - const newSource = ts.createSourceFile('temp.ts', `type ${name} = ${typeString}`, sourceFile.languageVersion); - - return newSource.statements[0]; -} - - /** * Determine if a ts.HeritageClause is React HeritageClause * diff --git a/src/transforms/collapse-intersection-interfaces-transform.ts b/src/transforms/collapse-intersection-interfaces-transform.ts index c4483c7..f04a9d1 100644 --- a/src/transforms/collapse-intersection-interfaces-transform.ts +++ b/src/transforms/collapse-intersection-interfaces-transform.ts @@ -39,10 +39,12 @@ export function collapseIntersectionInterfacesTransformFactoryFactory( .map((type: ts.TypeLiteralNode) => type.members) .reduce((all, members) => ts.createNodeArray(all.concat(members)), ts.createNodeArray([])); - return helpers.createTypeDeclarationStatement( + return ts.createTypeAliasDeclaration( + [], + [], node.name.text, + [], ts.createTypeLiteralNode(allMembers), - sourceFile, ); } diff --git a/src/transforms/react-hoist-generics-transform.ts b/src/transforms/react-hoist-generics-transform.ts index e26c42e..b2aa4c3 100644 --- a/src/transforms/react-hoist-generics-transform.ts +++ b/src/transforms/react-hoist-generics-transform.ts @@ -54,10 +54,10 @@ function hoist(reactClass: ts.ClassDeclaration, sourceFile: ts.SourceFile) { } const [propType, stateType] = reactType.typeArguments; - const propTypeName = `I${className}Props`; - const stateTypeName = `I${className}State`; - const propTypeDeclaration = helpers.createTypeDeclarationStatement(propTypeName, propType, sourceFile); - const stateTypeDeclaration = helpers.createTypeDeclarationStatement(stateTypeName, stateType, sourceFile); + const propTypeName = `${className}Props`; + const stateTypeName = `${className}State`; + const propTypeDeclaration = ts.createTypeAliasDeclaration([], [], propTypeName, [], propType); + const stateTypeDeclaration = ts.createTypeAliasDeclaration([], [], stateTypeName, [], stateType); const propTypeRef = ts.createTypeReferenceNode(propTypeName, []); const stateTypeRef = ts.createTypeReferenceNode(stateTypeName, []); const newClassStatement = insertTypeRefs(reactClass, propTypeRef, stateTypeRef); diff --git a/src/transforms/react-js-make-props-and-state-transform.ts b/src/transforms/react-js-make-props-and-state-transform.ts index bc82317..6aa9d1d 100644 --- a/src/transforms/react-js-make-props-and-state-transform.ts +++ b/src/transforms/react-js-make-props-and-state-transform.ts @@ -222,8 +222,8 @@ export function reactJSMakePropsAndStateInterfaceTransformFactoryFactory(typeChe console.warn('Bad value for propType', name, 'at', propertyAssignment.getStart()); return result; } - const typeValue = getTypeFromReactPropTypeExpression(propertyAssignment.initializer) - const propertySignature = ts.createPropertySignature(name, undefined, typeValue, undefined); + const typeValue = getTypeFromReactPropTypeExpression(propertyAssignment.initializer); + const propertySignature = ts.createPropertySignature([], name, undefined, typeValue, undefined); result.members.push(propertySignature) return result; }, ts.createTypeLiteralNode([])); diff --git a/test/collapse-intersection-interfaces-transform/empty-empty/output.tsx b/test/collapse-intersection-interfaces-transform/empty-empty/output.tsx index c2049e0..579668f 100644 --- a/test/collapse-intersection-interfaces-transform/empty-empty/output.tsx +++ b/test/collapse-intersection-interfaces-transform/empty-empty/output.tsx @@ -1,3 +1 @@ -type Foo = { - -}; \ No newline at end of file +type Foo = {}; diff --git a/test/end-to-end/basic/output.tsx b/test/end-to-end/basic/output.tsx index bd07c26..f0b58a2 100644 --- a/test/end-to-end/basic/output.tsx +++ b/test/end-to-end/basic/output.tsx @@ -1,12 +1,10 @@ import * as React from 'react'; -type IMyComponentProps = { +type MyComponentProps = {}; +type MyComponentState = void; -}; -type IMyComponentState = void; - -export default class MyComponent extends React.Component { +export default class MyComponent extends React.Component { render() { return
; } -} \ No newline at end of file +} diff --git a/test/end-to-end/initial-state-and-proprypes-and-set-state/output.tsx b/test/end-to-end/initial-state-and-proprypes-and-set-state/output.tsx index b81e124..64338c6 100644 --- a/test/end-to-end/initial-state-and-proprypes-and-set-state/output.tsx +++ b/test/end-to-end/initial-state-and-proprypes-and-set-state/output.tsx @@ -1,14 +1,14 @@ import * as React from 'react'; -type IMyComponentProps = { +type MyComponentProps = { baz: string; }; -type IMyComponentState = { +type MyComponentState = { dynamicState: number; foo: number; bar: string; }; -export default class MyComponent extends React.Component { +export default class MyComponent extends React.Component { state = { foo: 1, bar: 'str' }; render() { return
; @@ -16,4 +16,4 @@ export default class MyComponent extends React.Component { +export default class MyComponent extends React.Component { state = { foo: 1, bar: 'str' }; render() { return
; } -} \ No newline at end of file +} diff --git a/test/react-hoist-generics-transform/propless-stateless/output.tsx b/test/react-hoist-generics-transform/propless-stateless/output.tsx index a6b24f3..904d02c 100644 --- a/test/react-hoist-generics-transform/propless-stateless/output.tsx +++ b/test/react-hoist-generics-transform/propless-stateless/output.tsx @@ -1,10 +1,8 @@ import * as React from 'react'; -type IMyComponentProps = { - -}; -type IMyComponentState = void; -export default class MyComponent extends React.Component { +type MyComponentProps = {}; +type MyComponentState = void; +export default class MyComponent extends React.Component { render() { return
; } diff --git a/test/react-hoist-generics-transform/props-and-state/output.tsx b/test/react-hoist-generics-transform/props-and-state/output.tsx index 841ed21..dbebeed 100644 --- a/test/react-hoist-generics-transform/props-and-state/output.tsx +++ b/test/react-hoist-generics-transform/props-and-state/output.tsx @@ -1,14 +1,14 @@ import * as React from 'react'; -type IMyComponentProps = { +type MyComponentProps = { foo: string; bar: object; }; -type IMyComponentState = { +type MyComponentState = { baz: string; [k: string]: string; }; -export default class MyComponent extends React.Component { +export default class MyComponent extends React.Component { render() { return
; } diff --git a/test/react-js-make-props-and-state-transform/propless-stateless/output.tsx b/test/react-js-make-props-and-state-transform/propless-stateless/output.tsx index 3eae241..d61f77b 100644 --- a/test/react-js-make-props-and-state-transform/propless-stateless/output.tsx +++ b/test/react-js-make-props-and-state-transform/propless-stateless/output.tsx @@ -1,8 +1,6 @@ import * as React from 'react'; -export default class MyComponent extends React.Component<{ - - }, void> { +export default class MyComponent extends React.Component<{}, void> { render() { return
; } diff --git a/test/react-js-make-props-and-state-transform/set-state-advanced/output.tsx b/test/react-js-make-props-and-state-transform/set-state-advanced/output.tsx index 66b9845..a254578 100644 --- a/test/react-js-make-props-and-state-transform/set-state-advanced/output.tsx +++ b/test/react-js-make-props-and-state-transform/set-state-advanced/output.tsx @@ -1,20 +1,6 @@ import * as React from 'react'; -export default class MyComponent extends React.Component<{ - }, { - foo: number; - bar: number; - } & { - baz: number; - } & { - something: { - big: number; - here: string; - of: { - a: number; - }[]; - }; - }> { +export default class MyComponent extends React.Component<{}, { foo: number; bar: number; } & { baz: number; } & { something: { big: number; here: string; of: { a: number; }[]; }; }> { render() { return