Тип TypeScript, который соответствует любому объекту, но не массивам - PullRequest
2 голосов
/ 10 апреля 2020

Я пытаюсь определить тип, который соответствует любому объекту / словарю, но НЕ массивам.

Моя первая попытка не сработала, так как массивы технически являются объектами под капотом:

const a:{[k:string]: any} = []; // works fine

Я также знаю, что можно создать обобщенную c "проверку", например, так:

type NoArray<T> = T extends any[] ? never : T;

Но это не то, что я ищу. Я хочу тип c не-generi, который работает следующим образом:

const a: NoArrayType = {}; // works fine
const a: NoArrayType = []; // TypeError

1 Ответ

2 голосов
/ 11 апреля 2020

Проблема с типом - это any в вашем объявлении типа. any - это обычно то, что вы хотите избегать в большинстве приложений для машинописи.

Массив - это просто объект, который можно индексировать с помощью числовых ключей c и который имеет несколько дополнительных методов. Фактически вы можете присвоить этому типу практически любое не примитивное значение.

const a: {[k:string]: any} = [1,2,3]; // works
const b: {[k:string]: any} = {a: 123}; // works
const c: {[k:string]: any} = () => { console.log(123) }; // works
const d: {[k:string]: any} = () => new AnyClass(); // works

Playground

Это работает по той же причине, что вы можете сделать следующее, потому что any - это единственный случай, когда машинопись всегда позволяет вам привести значение к.

const a: any = true
const b: any = {}
const c: any = new AnyClass()

Детская площадка

Итак, у вас есть несколько вариантов.

  1. Ограничьте свой тип, чтобы не приводить к any. Если вам известны возможные значения этих свойств, объявите их.
interface MyObjectType { [k: string]: number | string }
const a: MyObjectType = [] // fails
const b: MyObjectType = {} // works

Playground

Или, возможно, это JSON? Если это так, any не является правильным типом, поскольку вы знаете, что у него не может быть некоторых вещей (например, экземпляров классов или функций).

interface Json {
  [key: string]: string | number | boolean | Json | Json[]
}

const a: Json = [] // type error
const b: Json = {} // works

Playground

Или используйте тип unknown вместо any, что требует проверки типа во время выполнения перед использованием значений.
interface MyObjectType { [k: string]: unknown }

const a: MyObjectType = [] // type error
const b: MyObjectType = { prop: 123 } // works

// b.prop type here is: unknown
b.prop.toUpperCase() // type error

if (typeof b.prop === 'string') {
  // a.prop type here is: string
  console.log(b.prop.toUpperCase()) // works
}

Детская площадка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...