typescript 使用ts-morph时如何创建没有字符串/writer的TypeLiteral?

rjzwgtxy  于 2023-02-05  发布在  TypeScript
关注(0)|答案(2)|浏览(144)

我想用编程的方式创建这样的类型文件:

export type Car = {
    color: string;
    // ... tons of properties
};

使用ts-morph addTypeAlias方法似乎很容易做到这一点:

sourceFile.addTypeAlias({
    name: 'Car',
    type: theType,
    isExported: true,
});

虽然不幸的是这里的theType必须是string | WriterFunction。而且我希望它是一个TypeLiteral!有什么方法可以用我缺少的ts-morph来实现这个目的吗?当然我可以通过一些循环和字符串连接等方法将我的类型文本构造为字符串,但我真的希望避免这样构建我的文件-那么我还不如使用模板/存根文件和fs。
有没有其他更程序化/基于节点类的方法来实现这一点?

2ledvvac

2ledvvac1#

可以使用typescript库中的TypeLiteral类型定义类型Car的属性,然后将其作为类型参数传递给tsmorph中的addTypeAlias方法。

import { TypeLiteral } from 'typescript';

const carProperties = [
  { name: 'color', type: 'string' },
  // ... tons of properties
];

const typeLiteral = new TypeLiteral(
  carProperties.map(prop => {
    return {
      name: prop.name,
      type: prop.type,
    };
  })
);

sourceFile.addTypeAlias({
  name: 'Car',
  type: typeLiteral,
  isExported: true,
});
ulydmbyx

ulydmbyx2#

简介

让我们将以下Node.js版本视为当前版本:

$ node --version
v18.13.0

让我们把下面的npm版本当作当前版本:

$ npm --version
9.2.0

让我们将依赖项的以下版本视为当前版本(摘自package.json文件):

{
  <…>,
  "dependencies": {
    "ts-morph": "17.0.1",
    "typescript": "4.9.5"
  },
  "devDependencies": {
    "ts-node": "10.9.1"
  }
}

概述

虽然不幸的是这里的theType必须是string | WriterFunction。而且我希望它是一个TypeLiteral!有没有办法用我缺少的ts-morph来实现这一点?
目前,似乎没有直接的解决办法。
请参阅以下看似相关的GitHub问题:

有没有其他更程序化/基于节点类的方法来实现这一点?
让我们考虑一些可能的解决方案。

可能的解决方案:ts-morph:使用对象类型编写器(Writers.objectType()静态方法)

它可能被认为更具有编程性,但它仍然是一种基于编写器(而不是基于节点)的方法。
参考文献:

  • Writers.objectType()静态方法. ts-变形/作者. ts at 17.0.1·dsherret/ts-变形。
  • 相应的测试.可以作为文档. ts-形态/编写者测试. ts at 17.0.1·dsherret/ts-形态。

草稿示例

src/index-ts-morph.ts文件

import { Project, WriterFunction, Writers } from "ts-morph";

async function createFile(outputFilePath: string) {
    const project = new Project();
    const sourceFile = project.createSourceFile(
        outputFilePath,
        undefined,
        { overwrite: true }
    );

    const typeAliasDeclarations = [
        createExportedTypeAliasDeclaration("Book"),
        createExportedTypeAliasDeclaration("House"),
        createExportedTypeAliasDeclaration("Car"),
    ];
    sourceFile.addTypeAliases(typeAliasDeclarations);

    await sourceFile.save();
};

function createExportedTypeAliasDeclaration(name: string) {
    const writerFunction: WriterFunction = Writers.objectType({
        properties: [
            {
                name: "color",
                type: "string"
            }
        ]
    });
    return ({
        name: name,
        type: writerFunction,
        isExported: true,
    });
}

await createFile("output.ts");

运行脚本并检查其输出

$ npx ts-node src/index-ts-morph.ts
$ cat output.ts 
export type Book = {
        color: string;
    };
export type House = {
        color: string;
    };
export type Car = {
        color: string;
    };

请注意这个奇怪的凹痕。
可能是ts-morph缺陷造成的?

可能的解决方案:typescript:使用typescript代替ts-morph

参考文献:

草稿示例

src/index-typescript.ts文件

import { writeFile } from "fs/promises";
import ts from "typescript";
const { factory } = ts;

async function createFile(outputFilePath: string) {
    const typeAliasDeclarations = [
        createExportedTypeAliasDeclaration("Book"),
        createExportedTypeAliasDeclaration("House"),
        createExportedTypeAliasDeclaration("Car"),
    ];

    const printer = ts.createPrinter({
        newLine: ts.NewLineKind.LineFeed
    });
    const nodes = factory.createNodeArray(typeAliasDeclarations);
    const sourceFile = ts.createSourceFile(
        "this-name-is-ignored.ts",
        "",
        ts.ScriptTarget.Latest,
        false,
        ts.ScriptKind.TS
    );
    const printedString = printer.printList(
        ts.ListFormat.MultiLine,
        nodes,
        sourceFile
    );

    await writeFile(outputFilePath, printedString);
};

function createExportedTypeAliasDeclaration(name: string) {
    const colorPropertySignature = factory.createPropertySignature(
        undefined,
        factory.createIdentifier("color"),
        undefined,
        factory.createTypeReferenceNode(
            factory.createIdentifier("string"),
            undefined
        )
    );

    return factory.createTypeAliasDeclaration(
        [
            factory.createToken(ts.SyntaxKind.ExportKeyword)
        ],
        factory.createIdentifier(name),
        undefined,
        factory.createTypeLiteralNode([
            colorPropertySignature
        ])
    );
}

await createFile("output.ts");

运行脚本并检查其输出

$ npx ts-node src/index-typescript.ts
$ cat output.ts 
export type Book = {
    color: string;
};
export type House = {
    color: string;
};
export type Car = {
    color: string;
};

相关问题