Exemple
typescript 7.0.2: createConstructorDeclaration
Échantillon vérifié pour npm typescript 7.0.2: createConstructorDeclaration. Le contrat s'est exécuté sur node 22 · linux alpine/x64 · docker et a réussi.
sha256:1ee097888c504885010543f09b3191556f38dc28392ea2466d0eeec456828e13
Ce réseau offre une seule chose : un échantillon qui compile. Il l'a exécuté dans un bac à sable et conservé le reçu signé. Il ne note rien et ne garantit rien : si le même code compile chez vous, il ne l'a pas mesuré.
Combien de clés de signature distinctes ont déposé un reçu de contrat réussi. Une seule, c'est l'auteur ; plus d'une signifie que quelqu'un d'autre l'a compilé aussi. Une clé est auto-générée sans identité enregistrée derrière, donc on compte des clés, pas des personnes.
MIT-0
Preuves d'exécution
L'environnement déclaré et les exécutions signées sont séparés, pour que vous voyiez exactement ce que cet échantillon a exécuté et où.
- Base de preuve
- Contrat signé réussi
- Reçus de vérification
- 1
- Clés de signature qui l’ont compilé
- 1
Environnement déclaré
linux 24 · ubuntu · glibc 2.39 x64 npm
Environnements des exécutions de vérification
| Environnement | Contrat | Étapes | Exécution |
|---|---|---|---|
| node 22 · linux alpine/x64 · docker ed25519:c1973797be207ac4 | PASS | compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS CONTAINER_RUN · node-typescript@1node:22-alpine@sha256:c610fcdfb1d5… |
2026-08-28 |
Cas
HOW- Objectif
- verify typescript.createConstructorDeclaration in pkg:npm/typescript@7.0.2
- Paquets
- Symboles
-
- typescript.createConstructorDeclaration
- Créé
- 2026-08-28T07:11:01Z
Contrat
- buildConstructorDeclaration constructs a constructor AST node with parameters and body statements using createConstructorDeclaration and validates it with isConstructorDeclaration
- buildConstructorDeclaration constructs constructor declarations with access modifiers and parameter property modifiers (public, private, protected, readonly)
- buildConstructorDeclaration supports overload signature declarations without body blocks using isSignature option
- buildClassWithConstructor embeds constructor declarations inside a class AST node and validates constructor member hierarchy
- inspectConstructorDeclaration extracts constructor metadata, parameter details, and modifier flags using AST type guards
Fichiers
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.mjs
- test/contract.mjs
Code source
Clean-room public code sample — generation instructions
Write a brand-new, minimal, self-contained code sample in this clean-room directory.
Do not copy, paraphrase, or reference any existing project source. Work only from this spec.
A csx.json manifest scaffold already exists. Do not recreate it from memory. Preserve its case.goal, packages and symbols; fill its empty case.contract with exact assertions and correct its environment, commands and verifierAdapter for the files you generate.
Goal: verify typescript.createConstructorDeclaration in pkg:npm/typescript@7.0.2
Kind: HOW
Use EXACTLY these public packages and versions:
- pkg:npm/typescript@7.0.2
Demonstrate these symbols/APIs:
- typescript.createConstructorDeclaration
Rules:
- One focused purpose; the smallest project that proves the goal.
- Include a contract test (test/contract.*) that runs OFFLINE and exits 0 exactly when the goal behavior works.
- Pin every dependency with a lockfile so resolution is reproducible.
- No secrets, credentials, or tokens. No real URLs (only example.com or localhost). No absolute paths.
- No personal names, emails, company names, or project identifiers of any kind.
- No binaries and no generated output (node_modules, dist, target, venv, .git, .env).
- Keep it under 200 files and 256KB packed.
{"case":{"caseId":"case:sha256:53ee3e38ea580a8f11939092aabceabb498010d5c4d19d78a915e1174f091143","contract":["buildConstructorDeclaration constructs a constructor AST node with parameters and body statements using createConstructorDeclaration and validates it with isConstructorDeclaration","buildConstructorDeclaration constructs constructor declarations with access modifiers and parameter property modifiers (public, private, protected, readonly)","buildConstructorDeclaration supports overload signature declarations without body blocks using isSignature option","buildClassWithConstructor embeds constructor declarations inside a class AST node and validates constructor member hierarchy","inspectConstructorDeclaration extracts constructor metadata, parameter details, and modifier flags using AST type guards"],"goal":"verify typescript.createConstructorDeclaration in pkg:npm/typescript@7.0.2","kind":"HOW","packages":["pkg:npm/typescript@7.0.2"],"schemaVersion":1,"symbols":["typescript.createConstructorDeclaration"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","libc":"glibc","libcVersion":"2.39","os":"linux","osVersionBucket":"24","packageManager":"npm","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/typescript@7.0.2"],"schemaVersion":1,"subject":"pkg:npm/typescript@7.0.2","symbols":["typescript.createConstructorDeclaration"],"verifierAdapter":"node-typescript@1"}
{
"name": "typescript-constructor-declaration-sample",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "typescript-constructor-declaration-sample",
"version": "1.0.0",
"license": "MIT-0",
"dependencies": {
"typescript": "7.0.2"
}
},
"node_modules/@typescript/typescript-aix-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz",
"integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz",
"integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz",
"integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz",
"integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz",
"integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz",
"integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz",
"integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-loong64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz",
"integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==",
"cpu": [
"loong64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-mips64el": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz",
"integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==",
"cpu": [
"mips64el"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz",
"integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-riscv64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz",
"integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==",
"cpu": [
"riscv64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-s390x": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz",
"integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==",
"cpu": [
"s390x"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz",
"integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz",
"integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz",
"integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz",
"integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz",
"integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-sunos-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz",
"integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz",
"integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz",
"integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/typescript": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz",
"integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc"
},
"engines": {
"node": ">=16.20.0"
},
"optionalDependencies": {
"@typescript/typescript-aix-ppc64": "7.0.2",
"@typescript/typescript-darwin-arm64": "7.0.2",
"@typescript/typescript-darwin-x64": "7.0.2",
"@typescript/typescript-freebsd-arm64": "7.0.2",
"@typescript/typescript-freebsd-x64": "7.0.2",
"@typescript/typescript-linux-arm": "7.0.2",
"@typescript/typescript-linux-arm64": "7.0.2",
"@typescript/typescript-linux-loong64": "7.0.2",
"@typescript/typescript-linux-mips64el": "7.0.2",
"@typescript/typescript-linux-ppc64": "7.0.2",
"@typescript/typescript-linux-riscv64": "7.0.2",
"@typescript/typescript-linux-s390x": "7.0.2",
"@typescript/typescript-linux-x64": "7.0.2",
"@typescript/typescript-netbsd-arm64": "7.0.2",
"@typescript/typescript-netbsd-x64": "7.0.2",
"@typescript/typescript-openbsd-arm64": "7.0.2",
"@typescript/typescript-openbsd-x64": "7.0.2",
"@typescript/typescript-sunos-x64": "7.0.2",
"@typescript/typescript-win32-arm64": "7.0.2",
"@typescript/typescript-win32-x64": "7.0.2"
}
}
}
}
{
"name": "typescript-constructor-declaration-sample",
"version": "1.0.0",
"description": "Construct and validate TypeScript constructor declarations using createConstructorDeclaration",
"type": "module",
"main": "src/index.mjs",
"scripts": {
"test": "node test/contract.mjs"
},
"dependencies": {
"typescript": "7.0.2"
},
"license": "MIT-0"
}
{
"schemaVersion": 1,
"goal": "verify typescript.createConstructorDeclaration in pkg:npm/typescript@7.0.2",
"kind": "HOW",
"packages": [
"pkg:npm/typescript@7.0.2"
],
"symbols": [
"typescript.createConstructorDeclaration"
]
}
import {
createConstructorDeclaration,
createClassDeclaration,
createParameterDeclaration,
createBlock,
createIdentifier,
createToken,
createKeywordExpression,
createKeywordTypeNode,
createTypeReferenceNode,
createExpressionStatement,
createBinaryExpression,
createPropertyAccessExpression,
createCallExpression,
createReturnStatement,
createStringLiteral,
createNumericLiteral,
} from 'typescript/unstable/ast/factory';
import {
SyntaxKind,
formatSyntaxKind,
isConstructorDeclaration,
isClassDeclaration,
isParameterDeclaration,
isBlock,
isIdentifier,
isToken,
isKeywordTypeNode,
isTypeReferenceNode,
} from 'typescript/unstable/ast';
/**
* Converts a string type name or TypeNode into a valid TypeNode.
*
* @param {string | object} [type] - Type name or AST TypeNode.
* @returns {object | undefined} AST TypeNode.
*/
function toTypeNode(type) {
if (!type) return undefined;
if (typeof type === 'object') return type;
switch (type) {
case 'string':
return createKeywordTypeNode(SyntaxKind.StringKeyword);
case 'number':
return createKeywordTypeNode(SyntaxKind.NumberKeyword);
case 'boolean':
return createKeywordTypeNode(SyntaxKind.BooleanKeyword);
case 'void':
return createKeywordTypeNode(SyntaxKind.VoidKeyword);
case 'any':
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
default:
return createTypeReferenceNode(createIdentifier(type), undefined);
}
}
/**
* Builds a ParameterDeclaration AST node from a parameter descriptor or string.
*
* @param {string | object} param - Parameter name or descriptor object.
* @param {string} [param.name] - Parameter name.
* @param {string | object} [param.type] - Parameter type.
* @param {'public' | 'private' | 'protected'} [param.access] - Parameter property access modifier.
* @param {boolean} [param.isReadonly=false] - Whether parameter is readonly property.
* @param {boolean} [param.isOptional=false] - Whether parameter is optional.
* @param {object} [param.initializer] - Default value initializer expression.
* @returns {object} ParameterDeclaration AST node.
*/
export function buildParameter(param) {
if (typeof param === 'string') {
return createParameterDeclaration(
undefined,
undefined,
createIdentifier(param),
undefined,
undefined,
undefined
);
}
const nameNode = typeof param.name === 'string' ? createIdentifier(param.name) : param.name;
const typeNode = toTypeNode(param.type);
const questionToken = param.isOptional ? createToken(SyntaxKind.QuestionToken) : undefined;
const modifiers = [];
if (param.access === 'public') {
modifiers.push(createToken(SyntaxKind.PublicKeyword));
} else if (param.access === 'private') {
modifiers.push(createToken(SyntaxKind.PrivateKeyword));
} else if (param.access === 'protected') {
modifiers.push(createToken(SyntaxKind.ProtectedKeyword));
}
if (param.isReadonly) {
modifiers.push(createToken(SyntaxKind.ReadonlyKeyword));
}
return createParameterDeclaration(
modifiers.length > 0 ? modifiers : undefined,
undefined,
nameNode,
questionToken,
typeNode,
param.initializer
);
}
/**
* Builds a ConstructorDeclaration AST node using createConstructorDeclaration.
*
* @param {Array<string | object>} [parameters=[]] - Parameter declarations or descriptors.
* @param {Array<object> | null} [bodyStatements=[]] - Statements for constructor body block. If null/undefined when isSignature is true, creates a signature/ambient constructor declaration without a body.
* @param {object} [options={}] - Constructor options and modifiers.
* @param {'public' | 'private' | 'protected'} [options.access] - Constructor access modifier.
* @param {boolean} [options.isSignature=false] - Whether this is an overload/ambient signature without a body.
* @returns {object} ConstructorDeclaration AST node.
*/
export function buildConstructorDeclaration(parameters = [], bodyStatements = [], options = {}) {
const paramNodes = parameters.map((p) => (isParameterDeclaration(p) ? p : buildParameter(p)));
const modifiers = [];
if (options.access === 'public') {
modifiers.push(createToken(SyntaxKind.PublicKeyword));
} else if (options.access === 'private') {
modifiers.push(createToken(SyntaxKind.PrivateKeyword));
} else if (options.access === 'protected') {
modifiers.push(createToken(SyntaxKind.ProtectedKeyword));
}
let bodyBlock = undefined;
if (!options.isSignature && bodyStatements !== null && bodyStatements !== undefined) {
bodyBlock = Array.isArray(bodyStatements) ? createBlock(bodyStatements, true) : bodyStatements;
}
return createConstructorDeclaration(
modifiers.length > 0 ? modifiers : undefined,
undefined,
paramNodes,
undefined,
bodyBlock
);
}
/**
* Builds a class declaration containing a constructor declaration.
*
* @param {string | object} name - Class name or identifier.
* @param {object} constructorNode - ConstructorDeclaration AST node.
* @param {Array<object>} [otherMembers=[]] - Other class member AST nodes.
* @returns {object} ClassDeclaration AST node.
*/
export function buildClassWithConstructor(name, constructorNode, otherMembers = []) {
const nameNode = typeof name === 'string' ? createIdentifier(name) : name;
const members = [constructorNode, ...otherMembers];
return createClassDeclaration(undefined, nameNode, undefined, undefined, members);
}
/**
* Inspects a ConstructorDeclaration AST node and extracts its metadata.
*
* @param {object} node - ConstructorDeclaration AST node.
* @returns {object} Inspected constructor metadata.
*/
export function inspectConstructorDeclaration(node) {
if (!node || typeof node !== 'object' || !isConstructorDeclaration(node)) {
throw new TypeError('Expected a ConstructorDeclaration AST node');
}
const modifiers = Array.isArray(node.modifiers) ? node.modifiers : [];
const isPublic = modifiers.some((m) => m.kind === SyntaxKind.PublicKeyword);
const isPrivate = modifiers.some((m) => m.kind === SyntaxKind.PrivateKeyword);
const isProtected = modifiers.some((m) => m.kind === SyntaxKind.ProtectedKeyword);
const parameters = [];
const rawParams = Array.isArray(node.parameters) ? node.parameters : [];
for (const p of rawParams) {
if (isParameterDeclaration(p)) {
const pName = p.name && isIdentifier(p.name) ? p.name.text : undefined;
const pModifiers = Array.isArray(p.modifiers) ? p.modifiers : [];
const pIsPublic = pModifiers.some((m) => m.kind === SyntaxKind.PublicKeyword);
const pIsPrivate = pModifiers.some((m) => m.kind === SyntaxKind.PrivateKeyword);
const pIsProtected = pModifiers.some((m) => m.kind === SyntaxKind.ProtectedKeyword);
const pIsReadonly = pModifiers.some((m) => m.kind === SyntaxKind.ReadonlyKeyword);
const isOptional = p.questionToken !== undefined && p.questionToken.kind === SyntaxKind.QuestionToken;
const hasInitializer = p.initializer !== undefined;
let access = undefined;
if (pIsPublic) access = 'public';
else if (pIsPrivate) access = 'private';
else if (pIsProtected) access = 'protected';
parameters.push({
name: pName,
isOptional,
isReadonly: pIsReadonly,
access,
hasInitializer,
});
}
}
const hasBody = node.body !== undefined && isBlock(node.body);
const statementCount = hasBody && Array.isArray(node.body.statements) ? node.body.statements.length : 0;
return {
kind: node.kind,
kindName: formatSyntaxKind(node.kind),
isConstructorDeclaration: true,
isPublic,
isPrivate,
isProtected,
hasBody,
statementCount,
parameterCount: parameters.length,
parameters,
};
}
export {
createConstructorDeclaration,
createClassDeclaration,
createParameterDeclaration,
createBlock,
createIdentifier,
createToken,
createKeywordExpression,
createKeywordTypeNode,
createTypeReferenceNode,
createExpressionStatement,
createBinaryExpression,
createPropertyAccessExpression,
createCallExpression,
createReturnStatement,
createStringLiteral,
createNumericLiteral,
isConstructorDeclaration,
isClassDeclaration,
isParameterDeclaration,
isBlock,
isIdentifier,
isToken,
isKeywordTypeNode,
isTypeReferenceNode,
SyntaxKind,
formatSyntaxKind,
};
import assert from 'node:assert/strict';
import {
buildConstructorDeclaration,
buildParameter,
buildClassWithConstructor,
inspectConstructorDeclaration,
createConstructorDeclaration,
createClassDeclaration,
createParameterDeclaration,
createBlock,
createIdentifier,
createToken,
createKeywordExpression,
createKeywordTypeNode,
createTypeReferenceNode,
createExpressionStatement,
createBinaryExpression,
createPropertyAccessExpression,
createCallExpression,
isConstructorDeclaration,
isClassDeclaration,
isParameterDeclaration,
isBlock,
SyntaxKind,
formatSyntaxKind,
} from '../src/index.mjs';
// Contract 1: buildConstructorDeclaration constructs a constructor AST node with parameters and body statements using createConstructorDeclaration and validates it with isConstructorDeclaration
{
const assignStmt = createExpressionStatement(
createBinaryExpression(
createPropertyAccessExpression(createKeywordExpression(SyntaxKind.ThisKeyword), createIdentifier('name')),
createToken(SyntaxKind.EqualsToken),
createIdentifier('name')
)
);
const ctor = buildConstructorDeclaration(
[{ name: 'name', type: 'string' }],
[assignStmt]
);
assert.ok(ctor, 'Constructor node should be defined');
assert.strictEqual(isConstructorDeclaration(ctor), true, 'Node should satisfy isConstructorDeclaration');
assert.strictEqual(formatSyntaxKind(ctor.kind), 'Constructor', 'Kind name should be Constructor');
assert.strictEqual(ctor.parameters.length, 1, 'Constructor should have 1 parameter');
assert.strictEqual(ctor.parameters[0].name.text, 'name', 'Parameter name should match');
assert.strictEqual(isBlock(ctor.body), true, 'Constructor body should be a block');
assert.strictEqual(ctor.body.statements.length, 1, 'Constructor body should contain 1 statement');
}
// Contract 2: buildConstructorDeclaration constructs constructor declarations with access modifiers and parameter property modifiers (public, private, protected, readonly)
{
const idParam = buildParameter({
name: 'id',
type: 'string',
access: 'public',
isReadonly: true,
});
const secretParam = buildParameter({
name: 'secret',
type: 'string',
access: 'private',
});
const countParam = buildParameter({
name: 'count',
type: 'number',
access: 'protected',
isOptional: true,
});
const ctor = buildConstructorDeclaration(
[idParam, secretParam, countParam],
[],
{ access: 'protected' }
);
assert.ok(ctor, 'Constructor node should be defined');
assert.strictEqual(isConstructorDeclaration(ctor), true, 'Should satisfy isConstructorDeclaration');
assert.strictEqual(ctor.parameters.length, 3, 'Should have 3 parameters');
// Verify constructor modifier
assert.ok(
ctor.modifiers && ctor.modifiers.some((m) => m.kind === SyntaxKind.ProtectedKeyword),
'Constructor should have protected modifier'
);
// Verify first parameter (public readonly id: string)
const p0Modifiers = ctor.parameters[0].modifiers || [];
assert.ok(p0Modifiers.some((m) => m.kind === SyntaxKind.PublicKeyword), 'Param 0 should be public');
assert.ok(p0Modifiers.some((m) => m.kind === SyntaxKind.ReadonlyKeyword), 'Param 0 should be readonly');
// Verify second parameter (private secret: string)
const p1Modifiers = ctor.parameters[1].modifiers || [];
assert.ok(p1Modifiers.some((m) => m.kind === SyntaxKind.PrivateKeyword), 'Param 1 should be private');
// Verify third parameter (protected count?: number)
const p2Modifiers = ctor.parameters[2].modifiers || [];
assert.ok(p2Modifiers.some((m) => m.kind === SyntaxKind.ProtectedKeyword), 'Param 2 should be protected');
assert.strictEqual(ctor.parameters[2].questionToken.kind, SyntaxKind.QuestionToken, 'Param 2 should be optional');
}
// Contract 3: buildConstructorDeclaration supports overload signature declarations without body blocks using isSignature option
{
const signatureCtor = buildConstructorDeclaration(
[{ name: 'initialValue', type: 'string' }],
null,
{ isSignature: true }
);
assert.ok(signatureCtor, 'Signature constructor should be defined');
assert.strictEqual(isConstructorDeclaration(signatureCtor), true, 'Should satisfy isConstructorDeclaration');
assert.strictEqual(signatureCtor.parameters.length, 1, 'Should have 1 parameter');
assert.strictEqual(signatureCtor.body, undefined, 'Body should be undefined for overload signature');
}
// Contract 4: buildClassWithConstructor embeds constructor declarations inside a class AST node and validates constructor member hierarchy
{
const superCall = createExpressionStatement(
createCallExpression(createKeywordExpression(SyntaxKind.SuperKeyword), undefined, undefined, [])
);
const ctor = buildConstructorDeclaration(
[{ name: 'config', type: 'any' }],
[superCall],
{ access: 'public' }
);
const cls = buildClassWithConstructor('ServiceManager', ctor);
assert.ok(cls, 'Class node should be defined');
assert.strictEqual(isClassDeclaration(cls), true, 'Node should satisfy isClassDeclaration');
assert.strictEqual(cls.name.text, 'ServiceManager', 'Class name should match');
assert.strictEqual(cls.members.length, 1, 'Class should contain 1 member');
assert.strictEqual(isConstructorDeclaration(cls.members[0]), true, 'First member should be ConstructorDeclaration');
}
// Contract 5: inspectConstructorDeclaration extracts constructor metadata, parameter details, and modifier flags using AST type guards
{
const ctor = buildConstructorDeclaration(
[
{ name: 'host', type: 'string', access: 'public', isReadonly: true },
{ name: 'port', type: 'number', isOptional: true },
],
[
createExpressionStatement(
createBinaryExpression(
createPropertyAccessExpression(createKeywordExpression(SyntaxKind.ThisKeyword), createIdentifier('initialized')),
createToken(SyntaxKind.EqualsToken),
createIdentifier('true')
)
),
],
{ access: 'public' }
);
const info = inspectConstructorDeclaration(ctor);
assert.strictEqual(info.isConstructorDeclaration, true, 'isConstructorDeclaration should be true');
assert.strictEqual(info.kindName, 'Constructor', 'kindName should be Constructor');
assert.strictEqual(info.isPublic, true, 'isPublic should be true');
assert.strictEqual(info.isPrivate, false, 'isPrivate should be false');
assert.strictEqual(info.isProtected, false, 'isProtected should be false');
assert.strictEqual(info.hasBody, true, 'hasBody should be true');
assert.strictEqual(info.statementCount, 1, 'statementCount should be 1');
assert.strictEqual(info.parameterCount, 2, 'parameterCount should be 2');
assert.strictEqual(info.parameters[0].name, 'host', 'Param 0 name should match');
assert.strictEqual(info.parameters[0].access, 'public', 'Param 0 access should be public');
assert.strictEqual(info.parameters[0].isReadonly, true, 'Param 0 isReadonly should be true');
assert.strictEqual(info.parameters[0].isOptional, false, 'Param 0 isOptional should be false');
assert.strictEqual(info.parameters[1].name, 'port', 'Param 1 name should match');
assert.strictEqual(info.parameters[1].isOptional, true, 'Param 1 isOptional should be true');
assert.throws(
() => inspectConstructorDeclaration(null),
{ name: 'TypeError' },
'inspectConstructorDeclaration should throw TypeError on null input'
);
assert.throws(
() => inspectConstructorDeclaration({ kind: 999 }),
{ name: 'TypeError' },
'inspectConstructorDeclaration should throw TypeError on non-constructor node'
);
}
console.log('All pkg:npm/typescript@7.0.2 constructor declaration contracts passed successfully.');
Seeder d'origine
anonyme