0

There is Props interface from third-party:

interface Props {
  id: string;
  name: string;
  age: number;
  approval: Approval
}

interface Approval {
  signature: string;
}

What is the solution that Props convert to array:

[
  {
    name: 'id',
    type: 'string'
  },
  {
    name: 'name',
    type:'string'
  },
  {
    name: 'age',
    type: 'number'
  },
  {
    name: 'approval',
    type: 'Approval'
  }
]

I have no idea that Typescript's interface can do this?

Update: Maybe it is not 'convert', somehow it just like 'reflect' or something else. Can I do this in babel?

However, I just want to get this array by Props.

4
  • Convert to a type or convert to a value? Commented Apr 6, 2023 at 6:55
  • Interfaces are part of the type system. They only exist during compilation for the compiler to check validity of code. They do not exist after compilation. It's not clear what or how you want to convert. Although, I'd note that the array doesn't have valid Props items, since they are all missing the mandatory attributes age and approval. Commented Apr 6, 2023 at 6:57
  • @VLAZ yes. Maybe it is not convert, I think it just like 'reflect' ? I know Golang can do this, but I don't know how to do in Typescript. Commented Apr 6, 2023 at 7:40
  • You can't do this; as VLAZ said, TypeScript's type system is erased upon compilation to JavaScript. Nothing of Props or Approval will exist at runtime for you to turn into an array. There is no reflection in TypeScript. You can either add a build step to do reflection, or you can refactor to write your array and generate types from it. The various options are described in answers to this question. Does that fully address the question, or am I missing something? Commented Apr 6, 2023 at 14:22

1 Answer 1

-1

Finally, I solved this problem through TS Compile API:


const {Project, SyntaxKind, Node, PropertySignature} = require('ts-morph');
const {resolve, dirname} = require('path');

    let res = {
        "Msg": [{
            "type": "string",
            "name": "type"
        }]
    }
    const project = new Project()
    project.addSourceFileAtPath(sourceFilePath)
    const sourceFile = project.getSourceFile(sourceFilePath)

    const msgInterfaces = sourceFile.getInterfaces()
        .filter((interfaceDecl) => {
            const interfaceName = interfaceDecl.getName()
            return interfaceName.endsWith("SDKType") && !interfaceName.includes("Response")
        })

    for (const msgInterface of msgInterfaces) {
        console.log(sourceFilePath, msgInterface.getName(), 'is building')

        const properties = msgInterface.getProperties()

        for (const property of properties) {
            const propStructure = property.getStructure()

            let name = propStructure.name
            let type = propStructure.type;

            if (BASIC_MSG_EIP712_TYPES[type]) {
                res["Msg"].push({
                    type: BASIC_MSG_EIP712_TYPES[type],
                    name,
                })
                continue
            }

            if (property.getType().isEnum()) {
                type = "string"
                res["Msg"].push({
                    type,
                    name,
                })
                continue;
            }

            if (property.getType().isArray()) {
                const ele = property.getType().getArrayElementType().getText()
                if (!Object.keys(BASIC_MSG_EIP712_TYPES).includes(ele)) continue;

                type = BASIC_MSG_EIP712_TYPES[ele] + "[]"
                res["Msg"].push({
                    type,
                    name
                })
                continue
            }

            if (property.getType().getSymbol().getDeclarations()[0].getKind() === SyntaxKind.InterfaceDeclaration) {
                type = "Type" + upperCaseFirst(snakeToCamel(name))
                res["Msg"].push({
                    type,
                    name,
                })

                const pps = property.getType().getProperties()
                res[type] = pps.map(p => {
                    return {
                        type: p.getValueDeclaration().getType().getText(),
                        name: p.getName(),
                    }
                })
                continue;
            }
        }

        project.createSourceFile(
            `./${dirname(filePath)}/${msgInterface.getName()}EIP712.ts`,
            `export const ${msgInterface.getName()}EIP712 = ${JSON.stringify(res, null, 2)} \n\n`,
            {overwrite: true}
        )
        project.saveSync()
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.