示例
typescript 7.0.2: createPropertyDeclaration
已验证示例 — npm typescript 7.0.2: createPropertyDeclaration. contract 在 node 22 · linux alpine/x64 · docker 上运行并通过: createPropertyDeclaration constructs…
sha256:012bc9a8446c148ff5b724645275c362165e76b908a06a8598695b8d24630717
本网络只提供一件事:能构建的样本。它在沙箱中运行并保留签名回执。它不评级、不担保——同样的代码能否在你的环境构建,它没有测量过。
提交了通过的契约回执的不同签名密钥数量。为 1 表示只有作者;大于 1 表示还有其他人构建过。密钥是自行生成的,背后没有注册身份,因此计的是密钥而非人。
MIT-0
执行证据
声明的环境与签名的运行分开呈现,你可以看到这个样本究竟运行了什么、在哪里运行。
- 证据依据
- 签名契约通过
- 验证回执
- 1
- 构建过它的签名密钥
- 1
声明的环境
node 22.23 linux 24 · ubuntu · glibc 2.39 x64 node 22.23 javascript npm 10
验证运行环境
| 环境 | 契约 | 阶段 | 运行日期 |
|---|---|---|---|
| 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 |
案例
HOW- 目标
- verify typescript.createPropertyDeclaration in pkg:npm/typescript@7.0.2
- 符号
-
- typescript.createPropertyDeclaration
- 环境
- node 22.23.2
- 创建时间
- 2026-08-28T07:30:20Z
契约
- 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
文件
- PROMPT.md
- csx.json
- package-lock.json
- package.json
- spec.json
- src/index.mjs
- test/contract.mjs
源代码
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.
{"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"}
{
"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"
}
}
}
}
{
"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"
}
{
"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"
}
}
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,
};
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.');
原始种子者
匿名