gpt4 book ai didi

typescript AST : How to get the asserted type?

转载 作者:行者123 更新时间:2023-12-05 05:55:33 25 4
gpt4 key购买 nike

我正在尝试解析一个类并为声明中没有值的属性声明创建默认值。

例如:

class MyClass {
name = 'My Class';
id: string;
}

functionCall<MyClass>() // <-- I get the hold of the type class here

我想生成这样的东西:

{
name: 'My Class',
id: 'I am generated'
}

我得到 MyClass来自 functionCall<MyClass>作为type: ts.InterfaceType节点并从那里解析属性:

const typeChecker = program.getTypeChecker();
const type = typeChecker.getTypeAtLocation(callExpression); // This is the node where `functioCall<MyClass>()` is

type.getProperties().forEach(symbol => {
// I am stuck here
});

我遇到的问题是,一些 symbolssymbol.valueDeclaration as undefined 不知道用什么知道

  1. 属性(property)类型
  2. 如果作业完成。

虽然我检查了一个 symbol.valueDeclaration存在并且如果他们的symbol.valueDeclaration.kind是一些关键字(如 SyntaxKind.StringKeyword )但它不适用于类似

class SomeClass {
noKeyword; // probably any?
}

如有任何帮助或指点,我们将不胜感激。

最佳答案

这是将运行时类型作为对象获取的脚本:


/*
Used to handle types from:
InterfaceDeclaration,
ClassDeclaration,
TypeLiteral
*/
function getTypeDescriptor(
property: ts.PropertyDeclaration | ts.PropertySignature,
typeChecker: ts.TypeChecker,
): ts.Expression {
const { type } = property;


if (type !== undefined) {

if (property.initializer) {

switch (property.initializer.kind) {
case ts.SyntaxKind.StringLiteral:
return ts.createLiteral('string');
case ts.SyntaxKind.FirstLiteralToken:
return ts.createLiteral('number');
}
}

return ts.createLiteral('any');
}

return getDescriptor(type, typeChecker);
}


// Create expression based on objects or property types
export function getDescriptor(type: ts.Node | undefined, typeChecker: ts.TypeChecker): ts.Expression {
if (!type) {
return ts.createLiteral('unknown');
}

switch (type.kind) {
case ts.SyntaxKind.PropertySignature:
return getDescriptor((type as ts.PropertySignature).type, typeChecker);
case ts.SyntaxKind.StringKeyword:
return ts.createLiteral('string');
case ts.SyntaxKind.NumberKeyword:
return ts.createLiteral('number');
case ts.SyntaxKind.BooleanKeyword:
return ts.createLiteral('boolean');
case ts.SyntaxKind.AnyKeyword:
return ts.createLiteral('any');
case ts.SyntaxKind.TypeAliasDeclaration:
case ts.SyntaxKind.TypeReference:
const symbol = typeChecker.getSymbolAtLocation((type as ts.TypeReferenceNode).typeName);
const declaration = ((symbol && symbol.declarations) || [])[0];
return getDescriptor(declaration, typeChecker);
case ts.SyntaxKind.ArrayType:
return ts.createArrayLiteral([getDescriptor((type as ts.ArrayTypeNode).elementType, typeChecker)]);
case ts.SyntaxKind.InterfaceDeclaration:
case ts.SyntaxKind.ClassDeclaration:
case ts.SyntaxKind.TypeLiteral:
return ts.createObjectLiteral(
(type as ts.TypeLiteralNode).members.map(member =>
ts.createPropertyAssignment(
member.name || '',
getTypeDescriptor(member as ts.PropertySignature, typeChecker),
),
),
);
default:
throw new Error('Unknown type ' + ts.SyntaxKind[type.kind]);
}
}

例子

有了这个类:

class X {
public id: number = 1;
}

属性初始值设定项如下所示:

<ref *2> TokenObject {
parent: <ref *1> NodeObject {
parent: NodeObject {
parent: [SourceFileObject],
kind: SyntaxKind.ClassDeclaration,
name: [IdentifierObject],
typeParameters: undefined,
heritageClauses: undefined,
members: [Array],
symbol: [SymbolObject]
},
kind: SyntaxKind.PropertyDeclaration,
decorators: undefined,
modifiers: [ [TokenObject], pos: 154, end: 162, transformFlags: 536870913 ],
name: IdentifierObject {},
questionToken: undefined,
type: TokenObject {
kind: SyntaxKind.NumberKeyword
},
initializer: [Circular *2],
symbol: SymbolObject {
escapedName: 'id',
declarations: [Array],
valueDeclaration: [Circular *1],
parent: [SymbolObject],
}
},
kind: SyntaxKind.NumericLiteral,
text: '1',
}

text: '1' 是属性的值,kind: SyntaxKind.NumericLiteraltext 的类型,parent.type.kind:SyntaxKind.NumberKeyword 是属性的实际定义类型。

P.S.:我知道的不多,但我希望它对你有所帮助

编辑:添加我如何使用转换器获取类型:

export function transformer(program: ts.Program, opts?: TransformerOptions) {
function visitor(ctx: ts.TransformationContext, sourcefile: ts.SourceFile, result: { seen: boolean }) {
const typeChecker = program.getTypeChecker();

const _visitor: ts.Visitor = (node: ts.Node) => {
if (ts.isCallExpression(node) && node.typeArguments && node.expression.getText(sourcefile) == 'generateRtti') {
const [type] = node.typeArguments;
const [argument] = node.arguments;
const fn = ts.createIdentifier(nameOfGenerateFunction);
const typeName = type.getText();
const typeSource = getDescriptor(type, typeChecker);
result.seen = true;
return ts.createCall(fn, undefined, [argument || ts.createStringLiteral(typeName), typeSource]);
}

return ts.visitEachChild(node, _visitor, ctx);
};

return _visitor;
}

return (ctx: ts.TransformationContext) => {
return (sourcefile: ts.SourceFile) => {
const result = { seen: false };
const newSourcefile = ts.visitNode(sourcefile, visitor(ctx, sourcefile, result));

if (result.seen) {
const generated_function = createGenerateFunction();
const statements: Array<ts.Statement> = [generated_function];

for (const statement of newSourcefile.statements) {
if (ts.isImportDeclaration(statement))
statements.splice(statements.length - 1, 0, statement);
else
statements.push(statement);
}

return ts.updateSourceFileNode(newSourcefile, statements);
}

return newSourcefile;
};
};
}

关于 typescript AST : How to get the asserted type?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69461435/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com