Skip to content

Type checking does not works for indexable type with number keys OR string keys #34611

Closed
@TokugawaTakeshi

Description

@TokugawaTakeshi

Try with newest TypeScript
TypeScript Version: 3.7.0-dev.20191018
Result: has not been fixed.

Search Terms:
typescript indexable type string keys or number keys

Code

enum PROPERTIES_TYPES {
  NUMBER = "NUMBER",
  STRING = "STRING"
  // ETC.
}

interface IStringPropertySpecification {
  type: PROPERTIES_TYPES.STRING;
  required: boolean;
  nullable?: boolean;
  newName?: string;
  emptyStringIsAllowed: boolean;
  allowedValues?: Array<string>;
  invalidValueSubstitution: string;
  defaultValue?: string;
}

interface IObjectDataSpecification__StringKeys {
  nameForLogging: string;
  properties: {
    [propertyName: string]: IStringPropertySpecification;
  };
}

interface IObjectDataSpecification__NumberKeys {
  nameForLogging: string;
  properties: {
    [propertyName: number]: IStringPropertySpecification;
  };
}

type ObjectDataSpecification = IObjectDataSpecification__StringKeys | IObjectDataSpecification__NumberKeys;


const dataSpecification: ObjectDataSpecification = {
  nameForLogging: "Test",
  properties: {
    foo: "asdfsadffsd" // Valid!!! No type errors!
  }
};

Expected behavior:

The error occurrence. I suppose, it must be:
TS2322 Type 'string' is not assignable to type ObjectDataSpecification

Actual behavior:

TypeScript ignores this error. However, my PhpStorm knows right autocompletes:

Autocomplete

Playground Link: https://jsfiddle.net/pfg1mq96/

Why I need so strange type as ObjectDataSpecification?

The ObjectDataSpecification has been created for external data validation. It's known in advance, which type external data SHOULD be, but it's unknown in advance, which data ACTUALLY WILL BE. If data satisfies ObjectDataSpecification, it will be cast as below:

const validData: IValidData = rawData as IValidData;

In above case, IValidData will be:

interface IValidData { foo: string; }

Normally, programmers should not create type like:

type ConfusingType {
  1: string;
  foo: number;
}

However I can't hope for high-quality API in the team work, The API team could define ANYTHING includes strange structure like above ConfusingType . Even it happens, I must to describe the ConfusingType with my ObjectDataSpecification. It will be:

const dataSpecification: ObjectDataSpecification = {
  nameForLogging: "ConfusingType ",
  properties: {
    1: {
      type: PROPERTIES_TYPES.STRING,
      required: true,
      emptyStringIsAllowed: false,
      invalidValueSubstitution: "---"
    },
    foo: {
      type: PROPERTIES_TYPES.NUMBER,
      required: true,
      numberType: NUMBER_TYPES.NATURAL_NUMBER,
      invalidValueSubstitution: 1
    }
  }
};

Then, my library validates external data according to dataSpecification.

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions