validation.ts ×43

Frontier kind: Code frontier

unlabeled · c_6e6dbe8a423b

257 tests · 3558 LOC · 19 files · introduces 0 tests · 180 LOC · 1 file

Introduces — evidence that enters the hierarchy at this concept

Code
43 ranges180 lines · 1 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
523 ranges3558 lines · 19 files · Browse complete extent
All tests (intent)
257 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

1 file ranked by introduced lines: 180 introduced LOC across 43 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/base/common/validation.ts 180 introduced LOC · 43 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- validation.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { mapFilter } from './arrays.js';
7 > import { IJSONSchema } from './jsonSchema.js';
8 >
9 > export interface IValidator<T> {
10 > validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError };
11 >
12 > getJSONSchema(): IJSONSchema;
13 > }
14 >
15 > export abstract class ValidatorBase<T> implements IValidator<T> {
16 > abstract validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError };
17 >
18 > abstract getJSONSchema(): IJSONSchema;
19 >
20 > validateOrThrow(content: unknown): T {
21 const result = this.validate(content);
22 if (result.error) {
25 return result.content;
26 }
27 > } validation.ts
28 >
29 > export type ValidatorType<T> = T extends IValidator<infer U> ? U : never;
30 >
31 > export interface ValidationError {
32 > message: string;
33 > }
34 >
35 > type TypeOfMap = {
36 > string: string;
37 > number: number;
38 > boolean: boolean;
39 > object: object;
40 > null: null;
41 > };
42 >
43 > class TypeofValidator<TKey extends keyof TypeOfMap> extends ValidatorBase<TypeOfMap[TKey]> {
44 > constructor(private readonly type: TKey) {
45 > super();
46 > }
47 >
48 > validate(content: unknown): { content: TypeOfMap[TKey]; error: undefined } | { content: undefined; error: ValidationError } {
49 if (typeof content !== this.type) {
50 return { content: undefined, error: { message: `Expected ${this.type}, but got ${typeof content}` } };
53 return { content: content as TypeOfMap[TKey], error: undefined };
54 }
56 > getJSONSchema(): IJSONSchema {
57 return { type: this.type };
58 }
59 > } validation.ts
60 >
61 > const vStringValidator = new TypeofValidator('string');
62 > export function vString(): ValidatorBase<string> { return vStringValidator; }
63 >
64 > const vNumberValidator = new TypeofValidator('number');
65 > export function vNumber(): ValidatorBase<number> { return vNumberValidator; }
66 >
67 > const vBooleanValidator = new TypeofValidator('boolean');
68 > export function vBoolean(): ValidatorBase<boolean> { return vBooleanValidator; }
69 >
70 > const vObjAnyValidator = new TypeofValidator('object');
71 > export function vObjAny(): ValidatorBase<object> { return vObjAnyValidator; }
72 >
73 >
74 > class UncheckedValidator<T> extends ValidatorBase<T> {
75 > validate(content: unknown): { content: T; error: undefined } {
76 return { content: content as T, error: undefined };
77 }
79 > getJSONSchema(): IJSONSchema {
80 return {};
81 }
82 > } validation.ts
83 >
84 > export function vUnchecked<T>(): ValidatorBase<T> {
85 return new UncheckedValidator<T>();
86 }
88 > class UndefinedValidator extends ValidatorBase<undefined> {
89 > validate(content: unknown): { content: undefined; error: undefined } | { content: undefined; error: ValidationError } {
90 if (content !== undefined) {
91 return { content: undefined, error: { message: `Expected undefined, but got ${typeof content}` } };
94 return { content: undefined, error: undefined };
95 }
97 > getJSONSchema(): IJSONSchema {
98 return {};
99 }
100 > } validation.ts
101 >
102 > export function vUndefined(): ValidatorBase<undefined> {
103 return new UndefinedValidator();
104 }
106 > export function vUnknown(): ValidatorBase<unknown> {
107 return vUnchecked();
108 }
110 > export type ObjectProperties = Record<string, unknown>;
111 >
112 > export class Optional<T extends IValidator<unknown>> {
113 > constructor(public readonly validator: T) { }
114 > }
115 >
116 > export function vOptionalProp<T>(validator: IValidator<T>): Optional<IValidator<T>> {
117 return new Optional(validator);
118 }
120 > type ExtractOptionalKeys<T> = {
121 > [K in keyof T]: T[K] extends Optional<IValidator<unknown>> ? K : never;
122 > }[keyof T];
123 >
124 > type ExtractRequiredKeys<T> = {
125 > [K in keyof T]: T[K] extends Optional<IValidator<unknown>> ? never : K;
126 > }[keyof T];
127 >
128 > export type vObjType<T extends Record<string, IValidator<unknown> | Optional<IValidator<unknown>>>> = {
129 > [K in ExtractRequiredKeys<T>]: T[K] extends IValidator<infer U> ? U : never;
130 > } & {
131 > [K in ExtractOptionalKeys<T>]?: T[K] extends Optional<IValidator<infer U>> ? U : never;
132 > };
133 >
134 > class ObjValidator<T extends Record<string, IValidator<unknown> | Optional<IValidator<unknown>>>> extends ValidatorBase<vObjType<T>> {
135 > constructor(private readonly properties: T) {
136 super();
137 }
139 > validate(content: unknown): { content: vObjType<T>; error: undefined } | { content: undefined; error: ValidationError } {
140 if (typeof content !== 'object' || content === null) {
141 return { content: undefined, error: { message: 'Expected object' } };
169 return { content: result, error: undefined };
170 }
172 > getJSONSchema(): IJSONSchema {
173 const requiredFields: string[] = [];
174 const schemaProperties: Record<string, IJSONSchema> = {};
191 return schema;
192 }
193 > } validation.ts
194 >
195 > export function vObj<T extends Record<string, IValidator<unknown> | Optional<IValidator<unknown>>>>(properties: T): ValidatorBase<vObjType<T>> {
196 return new ObjValidator(properties);
197 }
199 > class ArrayValidator<T> extends ValidatorBase<T[]> {
200 > constructor(private readonly validator: IValidator<T>) {
201 super();
202 }
204 > validate(content: unknown): { content: T[]; error: undefined } | { content: undefined; error: ValidationError } {
205 if (!Array.isArray(content)) {
206 return { content: undefined, error: { message: 'Expected array' } };
219 return { content: result, error: undefined };
220 }
222 > getJSONSchema(): IJSONSchema {
223 return {
224 type: 'array',
226 };
227 }
228 > } validation.ts
229 >
230 > export function vArray<T>(validator: IValidator<T>): ValidatorBase<T[]> {
231 return new ArrayValidator(validator);
232 }
234 > type vTupleType<T extends IValidator<unknown>[]> = { [K in keyof T]: ValidatorType<T[K]> };
235 >
236 > class TupleValidator<T extends IValidator<unknown>[]> extends ValidatorBase<vTupleType<T>> {
237 > constructor(private readonly validators: T) {
238 super();
239 }
241 > validate(content: unknown): { content: vTupleType<T>; error: undefined } | { content: undefined; error: ValidationError } {
242 if (!Array.isArray(content)) {
243 return { content: undefined, error: { message: 'Expected array' } };
260 return { content: result, error: undefined };
261 }
263 > getJSONSchema(): IJSONSchema {
264 return {
265 type: 'array',
267 };
268 }
269 > } validation.ts
270 >
271 > export function vTuple<T extends IValidator<unknown>[]>(...validators: T): ValidatorBase<vTupleType<T>> {
272 return new TupleValidator(validators);
273 }
275 > class UnionValidator<T extends IValidator<unknown>[]> extends ValidatorBase<ValidatorType<T[number]>> {
276 > constructor(private readonly validators: T) {
277 super();
278 }
280 > validate(content: unknown): { content: ValidatorType<T[number]>; error: undefined } | { content: undefined; error: ValidationError } {
281 let lastError: ValidationError | undefined;
282 for (const validator of this.validators) {
292 return { content: undefined, error: lastError! };
293 }
295 > getJSONSchema(): IJSONSchema {
296 return {
297 oneOf: mapFilter(this.validators, validator => {
303 };
304 }
305 > } validation.ts
306 >
307 > export function vUnion<T extends IValidator<unknown>[]>(...validators: T): ValidatorBase<ValidatorType<T[number]>> {
308 return new UnionValidator(validators);
309 }
311 > class EnumValidator<T extends string[]> extends ValidatorBase<T[number]> {
312 > constructor(private readonly values: T) {
313 super();
314 }
316 > validate(content: unknown): { content: T[number]; error: undefined } | { content: undefined; error: ValidationError } {
317 if (this.values.indexOf(content as string) === -1) {
318 return { content: undefined, error: { message: `Expected one of: ${this.values.join(', ')}` } };
321 return { content: content as T[number], error: undefined };
322 }
324 > getJSONSchema(): IJSONSchema {
325 return {
326 enum: this.values,
327 };
328 }
329 > } validation.ts
330 >
331 > export function vEnum<T extends string[]>(...values: T): ValidatorBase<T[number]> {
332 return new EnumValidator(values);
333 }
335 > class LiteralValidator<T extends string> extends ValidatorBase<T> {
336 > constructor(private readonly value: T) {
337 super();
338 }
340 > validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError } {
341 if (content !== this.value) {
342 return { content: undefined, error: { message: `Expected: ${this.value}` } };
345 return { content: content as T, error: undefined };
346 }
348 > getJSONSchema(): IJSONSchema {
349 return {
350 const: this.value,
351 };
352 }
353 > } validation.ts
354 >
355 > export function vLiteral<T extends string>(value: T): ValidatorBase<T> {
356 return new LiteralValidator(value);
357 }
359 > class LazyValidator<T> extends ValidatorBase<T> {
360 > constructor(private readonly fn: () => IValidator<T>) {
361 super();
362 }
364 > validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError } {
365 return this.fn().validate(content);
366 }
368 > getJSONSchema(): IJSONSchema {
369 return this.fn().getJSONSchema();
370 }
371 > } validation.ts
372 >
373 > export function vLazy<T>(fn: () => IValidator<T>): ValidatorBase<T> {
374 return new LazyValidator(fn);
375 }
377 > class UseRefSchemaValidator<T> extends ValidatorBase<T> {
378 > constructor(
379 private readonly _ref: string,
380 private readonly _validator: IValidator<T>
382 super();
383 }
385 > validate(content: unknown): { content: T; error: undefined } | { content: undefined; error: ValidationError } {
386 return this._validator.validate(content);
387 }
389 > getJSONSchema(): IJSONSchema {
390 return { $ref: this._ref };
391 }
392 > } validation.ts
393 >
394 > export function vWithJsonSchemaRef<T>(ref: string, validator: IValidator<T>): ValidatorBase<T> {
395 return new UseRefSchemaValidator(ref, validator);
396 }