CodeSampleX

Ejemplo

typescript 7.0.2: createPropertyDeclaration

Muestra verificada para npm typescript 7.0.2: createPropertyDeclaration. El contrato se ejecutó en node 22 · linux alpine/x64 · docker y pasó.

sha256:012bc9a8446c148ff5b724645275c362165e76b908a06a8598695b8d24630717

Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido. Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas. MIT-0

Evidencia de ejecución

El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.

Base de evidencia
Contrato firmado aprobado
Recibos de verificación
1
Claves de firma que lo compilaron
1
Entorno declarado node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm 10

Entornos de las ejecuciones de verificación

Entorno Contrato Etapas Ejecución
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

Caso

HOW
Objetivo
verify typescript.createPropertyDeclaration in pkg:npm/typescript@7.0.2
Paquetes
Símbolos
  • typescript.createPropertyDeclaration
Entorno
node 22.23.2
Creado
2026-08-28T07:30:20Z

Contrato

  1. createPropertyDeclaration constructs PropertyDeclaration AST nodes with modifiers, name, postfixToken, type, and initializer
  2. createClassProperty constructs property declarations from high-level options and primitive values
  3. isPropertyDeclaration validates whether an AST node is a PropertyDeclaration
  4. describePropertyDeclaration inspects a PropertyDeclaration node and extracts structural metadata or throws TypeError

Archivos

  • PROMPT.md
  • csx.json
  • package-lock.json
  • package.json
  • spec.json
  • src/index.mjs
  • test/contract.mjs

Descargar el artefacto de código fuente (tar.gz)

Código fuente

PROMPT.md
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.createPropertyDeclaration 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.createPropertyDeclaration
Constraints:
  - executionContext: node
Required runtime conditions:
  - ecosystem: npm
  - language: javascript
  - moduleSystem: cjs
  - packageManager: npm@10.9.8
  - runtime: node@22.23.2

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.
csx.json
{"case":{"caseId":"case:sha256:aea13401dfd1534ee749493457b716bf935adf23dd63f49e6a012a8139380509","constraints":{"executionContext":"node"},"contract":["createPropertyDeclaration constructs PropertyDeclaration AST nodes with modifiers, name, postfixToken, type, and initializer","createClassProperty constructs property declarations from high-level options and primitive values","isPropertyDeclaration validates whether an AST node is a PropertyDeclaration","describePropertyDeclaration inspects a PropertyDeclaration node and extracts structural metadata or throws TypeError"],"goal":"verify typescript.createPropertyDeclaration in pkg:npm/typescript@7.0.2","kind":"HOW","packages":["pkg:npm/typescript@7.0.2"],"schemaVersion":1,"symbols":["typescript.createPropertyDeclaration"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","distro":"ubuntu","ecosystem":"npm","executionContext":"node","language":"javascript","libc":"glibc","libcVersion":"2.39","moduleSystem":"cjs","os":"linux","osVersionBucket":"24","packageManager":"npm","packageManagerVersion":"10.9.8","runtime":"node","runtimeVersion":"22.23.2","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/typescript@7.0.2"],"schemaVersion":1,"subject":"pkg:npm/typescript@7.0.2","symbols":["typescript.createPropertyDeclaration"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "typescript-create-property-declaration-sample",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "typescript-create-property-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"
      }
    }
  }
}
package.json
{
  "name": "typescript-create-property-declaration-sample",
  "version": "1.0.0",
  "description": "Construct and validate TypeScript property declarations using createPropertyDeclaration",
  "type": "module",
  "main": "src/index.mjs",
  "scripts": {
    "test": "node test/contract.mjs"
  },
  "dependencies": {
    "typescript": "7.0.2"
  },
  "license": "MIT-0"
}
spec.json
{
  "schemaVersion": 1,
  "goal": "verify typescript.createPropertyDeclaration in pkg:npm/typescript@7.0.2",
  "kind": "HOW",
  "packages": [
    "pkg:npm/typescript@7.0.2"
  ],
  "symbols": [
    "typescript.createPropertyDeclaration"
  ],
  "constraints": {
    "executionContext": "node"
  },
  "runtimeConditions": {
    "ecosystem": "npm",
    "language": "javascript",
    "moduleSystem": "cjs",
    "packageManager": "npm@10.9.8",
    "runtime": "node@22.23.2"
  }
}
src/index.mjs
import {
  createPropertyDeclaration,
  createIdentifier,
  createToken,
  createKeywordTypeNode,
  createStringLiteral,
  createNumericLiteral,
} from 'typescript/unstable/ast/factory';

import {
  SyntaxKind,
  formatSyntaxKind,
  isPropertyDeclaration as tsIsPropertyDeclaration,
  isIdentifier,
} from 'typescript/unstable/ast';

const MODIFIER_MAP = {
  public: SyntaxKind.PublicKeyword,
  private: SyntaxKind.PrivateKeyword,
  protected: SyntaxKind.ProtectedKeyword,
  readonly: SyntaxKind.ReadonlyKeyword,
  static: SyntaxKind.StaticKeyword,
  abstract: SyntaxKind.AbstractKeyword,
  override: SyntaxKind.OverrideKeyword,
};

const KEYWORD_TYPE_MAP = {
  string: SyntaxKind.StringKeyword,
  number: SyntaxKind.NumberKeyword,
  boolean: SyntaxKind.BooleanKeyword,
  void: SyntaxKind.VoidKeyword,
  any: SyntaxKind.AnyKeyword,
  unknown: SyntaxKind.UnknownKeyword,
  never: SyntaxKind.NeverKeyword,
  undefined: SyntaxKind.UndefinedKeyword,
  null: SyntaxKind.NullKeyword,
  symbol: SyntaxKind.SymbolKeyword,
  bigint: SyntaxKind.BigIntKeyword,
  object: SyntaxKind.ObjectKeyword,
};

/**
 * Creates a PropertyDeclaration AST node from high-level options.
 *
 * @param {string | object} name - Property name string or Identifier AST node.
 * @param {object} [options] - Configuration options for the property.
 * @param {Array<string | number>} [options.modifiers] - Modifiers (e.g. ['public', 'readonly']).
 * @param {string | number | object} [options.type] - Type name string, SyntaxKind, or AST type node.
 * @param {boolean} [options.optional] - Whether the property is optional (appends `?`).
 * @param {boolean} [options.definite] - Whether the property is definite (appends `!`).
 * @param {any} [options.initializer] - Initializer AST node or literal value (string, number, boolean).
 * @returns {object} PropertyDeclaration AST node.
 */
export function createClassProperty(name, options = {}) {
  if (!name || (typeof name !== 'string' && typeof name !== 'object')) {
    throw new TypeError('Expected property name to be a non-empty string or AST node');
  }

  const nameNode = typeof name === 'string' ? createIdentifier(name) : name;

  let modifiersArray;
  if (options.modifiers && Array.isArray(options.modifiers)) {
    modifiersArray = options.modifiers.map((mod) => {
      if (typeof mod === 'number') {
        return createToken(mod);
      }
      if (typeof mod === 'string') {
        const kind = MODIFIER_MAP[mod.toLowerCase()];
        if (kind !== undefined) {
          return createToken(kind);
        }
        throw new Error(`Unknown modifier name: ${mod}`);
      }
      if (typeof mod === 'object' && mod !== null) {
        return mod;
      }
      throw new TypeError(`Invalid modifier: ${mod}`);
    });
  }

  let postfixToken;
  if (options.optional) {
    postfixToken = createToken(SyntaxKind.QuestionToken);
  } else if (options.definite) {
    postfixToken = createToken(SyntaxKind.ExclamationToken);
  }

  let typeNode;
  if (options.type !== undefined && options.type !== null) {
    if (typeof options.type === 'number') {
      typeNode = createKeywordTypeNode(options.type);
    } else if (typeof options.type === 'string') {
      const kind = KEYWORD_TYPE_MAP[options.type.toLowerCase()];
      if (kind !== undefined) {
        typeNode = createKeywordTypeNode(kind);
      } else {
        typeNode = createIdentifier(options.type);
      }
    } else if (typeof options.type === 'object') {
      typeNode = options.type;
    }
  }

  let initNode;
  if (options.initializer !== undefined) {
    if (typeof options.initializer === 'string') {
      initNode = createStringLiteral(options.initializer);
    } else if (typeof options.initializer === 'number') {
      initNode = createNumericLiteral(String(options.initializer));
    } else if (options.initializer === true) {
      initNode = createToken(SyntaxKind.TrueKeyword);
    } else if (options.initializer === false) {
      initNode = createToken(SyntaxKind.FalseKeyword);
    } else if (typeof options.initializer === 'object' && options.initializer !== null) {
      initNode = options.initializer;
    }
  }

  return createPropertyDeclaration(modifiersArray, nameNode, postfixToken, typeNode, initNode);
}

/**
 * Checks if a value is a PropertyDeclaration AST node safely without throwing on null or non-object.
 *
 * @param {any} node - Value or AST node to check.
 * @returns {boolean} True if the node is a PropertyDeclaration AST node.
 */
export function isPropertyDeclaration(node) {
  return Boolean(node && typeof node === 'object' && tsIsPropertyDeclaration(node));
}

/**
 * Describes a PropertyDeclaration node, extracting metadata.
 *
 * @param {object} node - PropertyDeclaration AST node.
 * @returns {object} Metadata object describing the property declaration.
 */
export function describePropertyDeclaration(node) {
  if (!isPropertyDeclaration(node)) {
    throw new TypeError('Expected a PropertyDeclaration AST node');
  }

  const name = node.name?._data?.text ?? (node.name?.escapedText || '<unnamed>');
  const modifierKinds = node.modifiers ? Array.from(node.modifiers).map((m) => formatSyntaxKind(m.kind)) : [];
  const hasQuestionToken = node.postfixToken?.kind === SyntaxKind.QuestionToken;
  const hasExclamationToken = node.postfixToken?.kind === SyntaxKind.ExclamationToken;
  const typeKind = node.type ? formatSyntaxKind(node.type.kind) : null;
  const hasInitializer = node.initializer !== undefined && node.initializer !== null;

  return {
    kind: node.kind,
    kindName: formatSyntaxKind(node.kind),
    name,
    modifiers: modifierKinds,
    isOptional: hasQuestionToken,
    isDefinite: hasExclamationToken,
    typeKind,
    hasInitializer,
  };
}

export {
  createPropertyDeclaration,
  createIdentifier,
  createToken,
  createKeywordTypeNode,
  createStringLiteral,
  createNumericLiteral,
  SyntaxKind,
  formatSyntaxKind,
  tsIsPropertyDeclaration,
  isIdentifier,
};
test/contract.mjs
import assert from 'node:assert/strict';
import {
  createPropertyDeclaration,
  createClassProperty,
  describePropertyDeclaration,
  createIdentifier,
  createToken,
  createKeywordTypeNode,
  createStringLiteral,
  createNumericLiteral,
  SyntaxKind,
  formatSyntaxKind,
  isPropertyDeclaration,
  isIdentifier,
} from '../src/index.mjs';

// Contract 1: createPropertyDeclaration constructs PropertyDeclaration AST nodes with modifiers, name, postfixToken, type, and initializer
{
  const idNode = createIdentifier('title');
  const typeNode = createKeywordTypeNode(SyntaxKind.StringKeyword);
  const initNode = createStringLiteral('Antigravity');
  const questionToken = createToken(SyntaxKind.QuestionToken);
  const modifierTokens = [createToken(SyntaxKind.ReadonlyKeyword)];

  const propNode = createPropertyDeclaration(
    modifierTokens,
    idNode,
    questionToken,
    typeNode,
    initNode
  );

  assert.ok(propNode, 'Property declaration node should be defined');
  assert.strictEqual(isPropertyDeclaration(propNode), true, 'Node should satisfy isPropertyDeclaration');
  assert.strictEqual(propNode.kind, SyntaxKind.PropertyDeclaration, 'Node kind should be PropertyDeclaration');
  assert.strictEqual(formatSyntaxKind(propNode.kind), 'PropertyDeclaration', 'Formatted kind name should be PropertyDeclaration');
  assert.strictEqual(isIdentifier(propNode.name), true, 'propNode.name should be an Identifier');
  assert.strictEqual(propNode.modifiers?.length, 1, 'propNode should have 1 modifier');
  assert.strictEqual(propNode.postfixToken?.kind, SyntaxKind.QuestionToken, 'postfixToken should be QuestionToken');
  assert.strictEqual(propNode.type?.kind, SyntaxKind.StringKeyword, 'type should be StringKeyword');
  assert.strictEqual(propNode.initializer?.kind, SyntaxKind.StringLiteral, 'initializer should be StringLiteral');

  // Minimal property declaration without modifiers, postfixToken, type, or initializer
  const simpleProp = createPropertyDeclaration(undefined, createIdentifier('count'), undefined, undefined, undefined);
  assert.ok(simpleProp, 'Simple property declaration should be defined');
  assert.strictEqual(isPropertyDeclaration(simpleProp), true, 'Simple property should satisfy isPropertyDeclaration');
  assert.strictEqual(simpleProp.modifiers, undefined, 'Simple property modifiers should be undefined');
  assert.strictEqual(simpleProp.postfixToken, undefined, 'Simple property postfixToken should be undefined');
  assert.strictEqual(simpleProp.type, undefined, 'Simple property type should be undefined');
  assert.strictEqual(simpleProp.initializer, undefined, 'Simple property initializer should be undefined');
}

// Contract 2: createClassProperty constructs property declarations from high-level options and primitive values
{
  const prop = createClassProperty('userId', {
    type: 'number',
    modifiers: ['public', 'readonly'],
    optional: true,
    initializer: 42,
  });

  assert.ok(prop, 'Class property should be created');
  assert.strictEqual(isPropertyDeclaration(prop), true, 'Class property should satisfy isPropertyDeclaration');
  assert.strictEqual(prop.modifiers?.length, 2, 'Should have 2 modifiers');
  assert.strictEqual(prop.postfixToken?.kind, SyntaxKind.QuestionToken, 'Should have QuestionToken');
  assert.strictEqual(prop.type?.kind, SyntaxKind.NumberKeyword, 'Should have NumberKeyword type');
  assert.strictEqual(prop.initializer?.kind, SyntaxKind.NumericLiteral, 'Should have NumericLiteral initializer');

  const definiteProp = createClassProperty('config', {
    type: 'object',
    modifiers: ['private'],
    definite: true,
  });
  assert.strictEqual(definiteProp.postfixToken?.kind, SyntaxKind.ExclamationToken, 'Should have ExclamationToken');
  assert.strictEqual(definiteProp.type?.kind, SyntaxKind.ObjectKeyword, 'Should have ObjectKeyword type');

  // Direct AST identifier input
  const astNameProp = createClassProperty(createIdentifier('customProp'), {
    type: SyntaxKind.BooleanKeyword,
  });
  assert.strictEqual(isPropertyDeclaration(astNameProp), true, 'Should accept AST Identifier for name');

  // Error handling
  assert.throws(() => createClassProperty(''), { name: 'TypeError' }, 'Should throw TypeError on empty name');
  assert.throws(() => createClassProperty(null), { name: 'TypeError' }, 'Should throw TypeError on null name');
  assert.throws(() => createClassProperty('invalidMod', { modifiers: ['invalidModifier'] }), /Unknown modifier name/, 'Should throw on unknown modifier');
}

// Contract 3: isPropertyDeclaration validates whether an AST node is a PropertyDeclaration
{
  const prop = createPropertyDeclaration(undefined, createIdentifier('x'), undefined, undefined, undefined);
  assert.strictEqual(isPropertyDeclaration(prop), true, 'PropertyDeclaration node should return true');

  const id = createIdentifier('x');
  assert.strictEqual(isPropertyDeclaration(id), false, 'Identifier node should return false');

  const token = createToken(SyntaxKind.ReadonlyKeyword);
  assert.strictEqual(isPropertyDeclaration(token), false, 'Modifier token should return false');

  assert.strictEqual(isPropertyDeclaration(null), false, 'null should return false');
  assert.strictEqual(isPropertyDeclaration(undefined), false, 'undefined should return false');
  assert.strictEqual(isPropertyDeclaration({}), false, 'Empty object should return false');
  assert.strictEqual(isPropertyDeclaration({ kind: SyntaxKind.Identifier }), false, 'Non-PropertyDeclaration object should return false');
}

// Contract 4: describePropertyDeclaration inspects a PropertyDeclaration node and extracts structural metadata or throws TypeError
{
  const prop = createClassProperty('createdAt', {
    type: 'string',
    modifiers: ['public', 'static'],
    optional: true,
    initializer: '2026-08-28',
  });

  const info = describePropertyDeclaration(prop);
  assert.strictEqual(info.kind, SyntaxKind.PropertyDeclaration, 'Kind should match PropertyDeclaration');
  assert.strictEqual(info.kindName, 'PropertyDeclaration', 'Kind name should be PropertyDeclaration');
  assert.strictEqual(info.name, 'createdAt', 'Name should be createdAt');
  assert.deepStrictEqual(info.modifiers, ['PublicKeyword', 'StaticKeyword'], 'Modifiers should match');
  assert.strictEqual(info.isOptional, true, 'isOptional should be true');
  assert.strictEqual(info.isDefinite, false, 'isDefinite should be false');
  assert.strictEqual(info.typeKind, 'StringKeyword', 'typeKind should be StringKeyword');
  assert.strictEqual(info.hasInitializer, true, 'hasInitializer should be true');

  assert.throws(() => describePropertyDeclaration(null), { name: 'TypeError' }, 'Should throw TypeError on null');
  assert.throws(() => describePropertyDeclaration(createIdentifier('notProp')), { name: 'TypeError' }, 'Should throw TypeError on non-property node');
}

console.log('All pkg:npm/typescript@7.0.2 contracts passed successfully.');

Seeder de origen

anónimo