diff --git a/src/DataParser.ts b/src/DataParser.ts index 475bb82..4fd1d47 100644 --- a/src/DataParser.ts +++ b/src/DataParser.ts @@ -1,8 +1,8 @@ import { InfoMetadata, NestedFieldMetadata } from "./MetadataParser"; -import { parseTypedValue, Value } from "./ValueParser"; +import { parseTypedValue, Value, ValueArray } from "./ValueParser"; -export function parseValue(token: string, infoMetadata: InfoMetadata): Value | Value[] { - let value: Value | Value[]; +export function parseValue(token: string, infoMetadata: InfoMetadata): Value | ValueArray { + let value: Value | ValueArray; const type = infoMetadata.number.type; switch (type) { case "NUMBER": @@ -25,7 +25,7 @@ export function parseValue(token: string, infoMetadata: InfoMetadata): Value | V return value; } -export function parseSingleValue(token: string, infoMetadata: InfoMetadata): Value | Value[] { +export function parseSingleValue(token: string, infoMetadata: InfoMetadata): Value | ValueArray { let value: Value | Value[]; if (infoMetadata.nested) { value = parseNestedValue(token, infoMetadata.nested); @@ -35,21 +35,21 @@ export function parseSingleValue(token: string, infoMetadata: InfoMetadata): Val return value; } -export function parseMultiValue(token: string, infoMetadata: InfoMetadata): Value[] { +export function parseMultiValue(token: string, infoMetadata: InfoMetadata): ValueArray { const values: Value[] = []; if (token.length > 0) { for (const part of token.split(infoMetadata.number.separator as string)) { - values.push(parseSingleValue(part, infoMetadata) as Value); + values.push(parseSingleValue(part, infoMetadata)); } } return values; } -export function parseNestedValue(token: string, nestedInfoMetadata: NestedFieldMetadata): Value[] { +export function parseNestedValue(token: string, nestedInfoMetadata: NestedFieldMetadata): ValueArray { const infoValues: Value[] = []; const parts = token.split(nestedInfoMetadata.separator); for (let i = 0; i < parts.length; ++i) { - infoValues.push(parseValue(parts[i], nestedInfoMetadata.items[i]) as Value); + infoValues.push(parseValue(parts[i], nestedInfoMetadata.items[i])); } return infoValues; } diff --git a/src/SampleDataParser.ts b/src/SampleDataParser.ts index 334e695..a9a1955 100644 --- a/src/SampleDataParser.ts +++ b/src/SampleDataParser.ts @@ -1,12 +1,12 @@ import { FieldMetadata } from "./MetadataParser"; import { parseValue } from "./DataParser"; -import { parseIntegerValue, Value } from "./ValueParser"; +import { parseIntegerValue, Value, ValueArray } from "./ValueParser"; export interface RecordSample { [index: string]: RecordSampleType; } -export type RecordSampleType = Genotype | Value | Value[]; +export type RecordSampleType = Genotype | Value | ValueArray; export type GenotypeAllele = number | null; export type GenotypeType = "het" | "hom_a" | "hom_r" | "miss" | "part"; @@ -36,7 +36,7 @@ export function parseRecordSample( } export function parseFormatValue(token: string, formatMetadata: FieldMetadata): RecordSampleType { - let value: Genotype | Value | Value[]; + let value: Genotype | Value | ValueArray; if (formatMetadata.id === "GT") { value = parseGenotype(token); } else { diff --git a/src/ValueParser.ts b/src/ValueParser.ts index 18ce1fd..549b743 100644 --- a/src/ValueParser.ts +++ b/src/ValueParser.ts @@ -1,7 +1,8 @@ import { MISSING } from "./Constants"; import { ValueType } from "./MetadataParser"; -export type Value = ValueCharacter | ValueFlag | ValueFloat | ValueInteger | ValueObject | ValueString; +export type Value = ValueCharacter | ValueFlag | ValueFloat | ValueInteger | ValueObject | ValueString | ValueArray; +export type ValueArray = Array>; export type ValueCharacter = string | null; export type ValueFlag = boolean | null; export type ValueFloat = number | null; diff --git a/src/VcfParser.ts b/src/VcfParser.ts index ab6682f..b83ea2f 100644 --- a/src/VcfParser.ts +++ b/src/VcfParser.ts @@ -5,6 +5,7 @@ import { parseStringArrayNonNullValues, parseStringValueNonNull, Value, + ValueArray, } from "./ValueParser"; import { MISSING } from "./Constants"; import { FieldMetadata, parseFormatMetadata, parseInfoMetadata } from "./MetadataParser"; @@ -22,7 +23,7 @@ export interface FieldMetadataContainer { } export interface InfoContainer { - [index: string]: Value | Value[]; + [index: string]: Value | ValueArray; } export function parseVcf(vcf: string): Container { diff --git a/src/VcfWriter.ts b/src/VcfWriter.ts index 339901a..be7d6db 100644 --- a/src/VcfWriter.ts +++ b/src/VcfWriter.ts @@ -2,7 +2,7 @@ import { Container, FormatMetadataContainer, Genotype, Metadata, Record, RecordS import { MISSING } from "./Constants"; import { FieldMetadataContainer, InfoContainer } from "./VcfParser"; import { FieldMetadata, NestedFieldMetadata } from "./MetadataParser"; -import { Value } from "./ValueParser"; +import { Value, ValueArray } from "./ValueParser"; import { RecordSampleType } from "./SampleDataParser"; export type Filter = { @@ -122,14 +122,14 @@ function writeInfo(infoFields: FieldMetadataContainer, infoValues: InfoContainer return vcf.join(";"); } -function writeInfoField(infoField: FieldMetadata, infoValue: Value | Value[]): string { +function writeInfoField(infoField: FieldMetadata, infoValue: Value | ValueArray): string { let vcf; if (infoField.number.count === 0) { vcf = infoField.id; } else if (infoField.number.count === 1) { - vcf = infoField.id + "=" + writeFieldValueSingle(infoField, infoValue as Value); + vcf = infoField.id + "=" + writeFieldValueSingle(infoField, infoValue); } else { - vcf = infoField.id + "=" + writeFieldValueMultiple(infoField, infoValue as Value[], ","); + vcf = infoField.id + "=" + writeFieldValueMultiple(infoField, infoValue as ValueArray, ","); } return vcf; } @@ -137,19 +137,19 @@ function writeInfoField(infoField: FieldMetadata, infoValue: Value | Value[]): s function writeFieldValueSingle(field: FieldMetadata, value: Value, missingValue = MISSING): string { let vcf; if (field.nested) { - vcf = writeFieldValueNested(field.nested, value as unknown as Value[]); + vcf = writeFieldValueNested(field.nested, value as ValueArray); } else { vcf = writeFieldValue(field, value, missingValue); } return vcf; } -function writeFieldValueMultiple(field: FieldMetadata, values: Value[], separator: string): string { +function writeFieldValueMultiple(field: FieldMetadata, values: ValueArray, separator: string): string { const vcf = []; for (const infoValue of values) { if (field.nested) { - vcf.push(writeFieldValueNested(field.nested, infoValue as unknown as Value[])); + vcf.push(writeFieldValueNested(field.nested, infoValue as ValueArray)); } else { vcf.push(writeFieldValue(field, infoValue, "")); } @@ -158,13 +158,13 @@ function writeFieldValueMultiple(field: FieldMetadata, values: Value[], separato return vcf.join(separator); } -function writeFieldValueNested(nestedField: NestedFieldMetadata, nestedValues: Value[]): string { +function writeFieldValueNested(nestedField: NestedFieldMetadata, nestedValues: ValueArray): string { const vcf = []; for (const [index, infoField] of nestedField.items.entries()) { if (infoField.number.count === 1) { vcf.push(writeFieldValueSingle(infoField, nestedValues[index], "")); } else { - vcf.push(writeFieldValueMultiple(infoField, nestedValues[index] as unknown as Value[], "&")); + vcf.push(writeFieldValueMultiple(infoField, nestedValues[index] as ValueArray, "&")); } } return vcf.join(nestedField.separator); @@ -224,7 +224,7 @@ function writeSampleValue(formatField: FieldMetadata, value: RecordSampleType): } else if (formatField.number.count === 1) { vcf = writeFieldValueSingle(formatField, value as Value); } else { - vcf = writeFieldValueMultiple(formatField, value as Value[], ","); + vcf = writeFieldValueMultiple(formatField, value as ValueArray, ","); } } return vcf; diff --git a/src/__tests__/VcfParser.test.ts b/src/__tests__/VcfParser.test.ts index 1cc69ae..5d4af5e 100644 --- a/src/__tests__/VcfParser.test.ts +++ b/src/__tests__/VcfParser.test.ts @@ -1,6 +1,6 @@ import { parseVcf } from "../VcfParser"; import { Container } from "../Vcf"; -import { Value } from "../ValueParser"; +import { ValueArray } from "../ValueParser"; // trailing info semicolon placed on purpose const vcf = ` @@ -197,7 +197,7 @@ test("parse vcf - escaped nested info values", () => { ["x0", "y0", "z0"], ["x1", "y1a,y1b", "z1"], ["x2", "y2", "z2"], - ] as unknown as Value, + ] as ValueArray, }, s: [], },