ts-auto-guard
Advanced tools
Comparing version 1.0.0-alpha.16 to 1.0.0-alpha.17
@@ -256,3 +256,3 @@ "use strict"; | ||
function objectCondition(varName, type, addDependency, project, path, arrayDepth, records, outFile, options) { | ||
var _a; | ||
var _a, _b; | ||
var conditions = []; | ||
@@ -286,5 +286,12 @@ var symbol = type.getSymbol(); | ||
} | ||
conditions.push.apply(conditions, __spread(propertiesConditions(varName, declaration | ||
var properties = declaration | ||
.getProperties() | ||
.map(function (p) { return ({ name: p.getName(), type: p.getType() }); }), addDependency, project, path, arrayDepth, records, outFile, options))); | ||
.map(function (p) { return ({ name: p.getName(), type: p.getType() }); }); | ||
conditions.push.apply(conditions, __spread(propertiesConditions(varName, properties, addDependency, project, path, arrayDepth, records, outFile, options))); | ||
var indexSignatures = declaration | ||
.getIndexSignatures() | ||
.map(function (p) { return ({ keyType: p.getKeyType(), type: p.getReturnType() }); }); | ||
if (indexSignatures.length) { | ||
conditions.push(indexSignaturesCondition(varName, indexSignatures, properties, addDependency, project, path, arrayDepth, records, outFile, options)); | ||
} | ||
} | ||
@@ -308,2 +315,7 @@ else { | ||
conditions.push.apply(conditions, __spread(propertiesConditions(varName, propertySignatures, addDependency, project, path, arrayDepth, records, outFile, options))); | ||
var typeArguments = type.getAliasTypeArguments(); | ||
if (((_b = type.getAliasSymbol()) === null || _b === void 0 ? void 0 : _b.getName()) === 'Record' && | ||
typeArguments.length === 2) { | ||
conditions.push(indexSignaturesCondition(varName, [{ keyType: typeArguments[0], type: typeArguments[1] }], propertySignatures, addDependency, project, path, arrayDepth, records, outFile, options)); | ||
} | ||
} | ||
@@ -438,2 +450,41 @@ catch (error) { | ||
} | ||
function indexSignatureConditions(objName, keyName, index, addDependency, project, path, arrayDepth, records, outFile, options) { | ||
var debug = options.debug; | ||
var expectedType = index.type.getText(); | ||
var expectedKeyType = index.keyType.getText(); | ||
var conditions = typeConditions(objName, index.type, addDependency, project, path + " " + objName, arrayDepth, true, records, outFile, options); | ||
var keyConditions = typeConditions(keyName, index.keyType, addDependency, project, path + " " + keyName, arrayDepth, true, records, outFile, options); | ||
if (debug) { | ||
var cleanKeyReplacer = '${key.toString().replace(/"/g, \'\\\\"\')}'; | ||
var evaluation = conditions && | ||
"evaluate(" + conditions + ", `" + path + "[\"" + cleanKeyReplacer + "\"]`, " + JSON.stringify(expectedType) + ", " + objName + ")"; | ||
var keyEvaluation = keyConditions && | ||
"evaluate(" + keyConditions + ", `" + path + " (key: \"" + cleanKeyReplacer + "\")`, " + JSON.stringify(expectedKeyType) + ", " + keyName + ")"; | ||
if (evaluation && keyEvaluation) { | ||
return ands(evaluation, keyEvaluation); | ||
} | ||
return evaluation || keyEvaluation; | ||
} | ||
if (conditions && keyConditions) { | ||
return ands(conditions, keyConditions); | ||
} | ||
// If we don't have both try and return one, or null if neither | ||
return conditions || keyConditions; | ||
} | ||
function indexSignaturesCondition(varName, indexSignatures, properties, addDependency, project, path, arrayDepth, records, outFile, options) { | ||
var conditions = ors.apply(void 0, __spread(indexSignatures | ||
.map(function (indexSignature) { | ||
return indexSignatureConditions('value', 'key', indexSignature, addDependency, project, path, arrayDepth, records, outFile, options); | ||
}) | ||
.filter(function (v) { return v !== null; }))); | ||
var staticKeysFilter = properties.length | ||
? "\n .filter(([key]) => ![" + properties | ||
.map(function (_a) { | ||
var name = _a.name; | ||
return "\"" + name + "\""; | ||
}) | ||
.join(',') + "].includes(key))" | ||
: ''; | ||
return "Object.entries(" + varName + ")" + staticKeysFilter + "\n .every(([key,value]) => " + conditions + ")"; | ||
} | ||
function generateTypeGuard(functionName, typeDeclaration, addDependency, project, records, outFile, options) { | ||
@@ -440,0 +491,0 @@ var debug = options.debug, shortCircuitCondition = options.shortCircuitCondition; |
{ | ||
"name": "ts-auto-guard", | ||
"version": "1.0.0-alpha.16", | ||
"version": "1.0.0-alpha.17", | ||
"description": "Generate type guard functions from TypeScript interfaces", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/rhys-vdw/ts-auto-guard", |
@@ -968,1 +968,65 @@ import { each, pull } from 'lodash' | ||
) | ||
testProcessProject( | ||
'generates type guards for dynamic object keys, including when mixed with static keys', | ||
{ | ||
'test.ts': ` | ||
/** @see {isTestType} ts-auto-guard:type-guard */ | ||
export interface TestType { | ||
someKey: "some" | "key" | ||
[index: string]: "dynamic" | "string" | ||
[index: number]: "also-dynamic" | "number" | ||
} | ||
` | ||
}, | ||
{ | ||
'test.guard.ts': ` | ||
import { TestType } from "./test"; | ||
export function isTestType(obj: any, _argumentName?: string): obj is TestType { | ||
return ( | ||
(obj !== null && | ||
typeof obj === "object" || | ||
typeof obj === "function") && | ||
(obj.someKey === "some" || | ||
obj.someKey === "key") && | ||
Object.entries(obj) | ||
.filter(([key]) => !["someKey"].includes(key)) | ||
.every(([key, value]) => ((value === "string" || | ||
value === "dynamic") && | ||
typeof key === "string" || | ||
(value === "number" || | ||
value === "also-dynamic") && | ||
typeof key === "number")) | ||
) | ||
} | ||
` | ||
} | ||
) | ||
testProcessProject( | ||
'generates type guards for Record types', | ||
{ | ||
'test.ts': ` | ||
/** @see {isTestType} ts-auto-guard:type-guard */ | ||
export type TestType = Record<string, "dynamic" | "string"> | ||
` | ||
}, | ||
{ | ||
'test.guard.ts': ` | ||
import { TestType } from "./test"; | ||
export function isTestType(obj: any, _argumentName?: string): obj is TestType { | ||
return ( | ||
(obj !== null && | ||
typeof obj === "object" || | ||
typeof obj === "function") && | ||
Object.entries(obj) | ||
.every(([key, value]) => ((value === "string" || | ||
value === "dynamic") && | ||
typeof key === "string")) | ||
) | ||
} | ||
` | ||
} | ||
) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
106103
1903