Почему 'any' можно присвоить любому типу без предварительного явного приведения его в соответствие?

Почему следующий фрагмент кода не вызывает ошибок или предупреждений?

{
    let x: number;
    let y: any;

    y = "hello";
    x = y;
}

Мои ожидания таковы: что-либо должно быть присвоено y, поскольку оно явно набирается как any, но только числа должны быть присвоены x, поскольку он явно набирается как number, и если any необходимо присвоить x, тогда это должно быть явно приведено к number:

x = y as number; 

Как можно считать текущее поведение приемлемым или, в первую очередь, хорошей идеей, а не ошибкой? Более того, есть ли способ заставить компилятор поднимать вопрос об этом и принимать только явное приведение?


Дополнительная информация:

  • tsc версия: 3.2.2
  • параметры компилятора:
{
    "target": "ES5",
    "noImplicitAny": true,
    "strictNullChecks": true,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "strictBindCallApply": true,
    "strictFunctionTypes": true,
    "strictPropertyInitialization": true
}

person Peter Varo    schedule 08.01.2019    source источник


Ответы (1)


Это определенное поведение any. Этот тип однотипен:

  • Назначаемый из любого другого типа
  • Можно присвоить любой другой тип (проблема, которую вы выделили)
  • С ним разрешены любые операции (индексация, вызов, доступ к свойствам, приложение оператора, все разрешено и никак не проверяется)

Есть несколько вариантов использования any. Пара примеров:

  • Разрешить простой переход от js к ts. Пока вы конвертируете код в машинописный текст, any может быть очень полезным, чтобы позволить вам успешно скомпилировать код, пока вы все еще конвертируете.
  • Разрешите легкое взаимодействие с существующим кодом JS (просто введите что-нибудь как any, и вы можете использовать его, как в JS). Хотя в конечном итоге вам, вероятно, лучше писать определения.

Как бы то ни было, сегодня я бы избегал any любой ценой в Typescript. В Typescript 3.0 представлен тип unknown, который ведет себя так, как вы ожидаете от any (т. Е. Вы можете назначить ему что угодно, но он не может быть назначен какому-либо другому типу). Подробнее о unknown здесь

Несколько способов избавиться от any:

  • noImplictAny настройка компилятора запрещает компилятору вывод any, если вы не укажете тип (вместо этого он выдаст ошибку)
  • no-unsafe-any Правило tslint, предотвращает использование any динамическим способом, т. Е. Использование разрешено только в том случае, если оно будет работать для {} | null | неопределенный
  • no-any правило tslint, запрещает любое и всякое использование any
person Titian Cernicova-Dragomir    schedule 08.01.2019
comment
Техническое описание состоит в том, что any одновременно является верхним типом (типом, который является супертипом любого другого типа) и нижним типом (тип - это подтип любого другого типа). Как вы понимаете, это довольно странно, и вы наткнулись на эту странность. В Modern Typescript также есть правильный верхний тип (unknown) и нижний тип (never). Фактически, из-за совместимости с JavaScript, undefined и null также являются нижними типами по умолчанию, но вы можете включить более строгую проверку. - person Jörg W Mittag; 08.01.2019