#javascript #typescript #types
Вопрос:
У меня есть следующий код , и машинопись выводит тип переменной d
как a string
, но на самом деле это должно было быть a string | number
. Я понимаю, что это происходит из-за функции машинописи, называемой сужением типа из-за назначений. Но это может стать довольно небезопасным (как подразумевается в следующем коде). Как отказаться от такого поведения?
interface Z {
name: string | number;
}
const f = (z: Z) => {
z.name = 200;
};
let z: Z = {
name: 2,
};
z.name = '2';
f(z);
const d = z.name;
Редактировать: Похоже, что один из способов обойти это-иметь какой-то линтер, делающий параметр немодифицируемым (но это очень ограничивает).
Ответ №1:
Я не уверен, что такое поведение «настраивается».
Ваша f
функция изменяет тип свойства z
своего аргумента, и я предполагаю , что компилятор не проверяет это так глубоко.
Если вы хотите, чтобы ввод был правильным, вам придется сообщить TypeScript, что вы что-то делаете с переменной.
Это сработало бы:
interface Z { name: string | number; }
const f = (z: Z) => {
z.name = 200;
return z;
};
let z: Z = { name: 2 };
z.name = '2';
z = f(z);
const d = z.name;
замена z
возвращенным значением заставляет TS «сохранять» изменение типа, которое происходит в f(z)
.
Или это:
interface Zbase { name: any }
interface Z extends Zbase { name: string | number; }
interface Znumber extends Zbase { name: number; }
interface Zstring extends Zbase { name: string; }
const f = (z: Z) => { z.name = 200; };
let z: Z = { name: 2 };
z.name = '2';
f(z);
const d = (z as Znumber).name;
Сейчас все это не очень красиво, но я обычно воспринимаю это как признак того, что я делаю что-то не так, когда пишу TS:
Почему а может name
быть а number
или а string
?
Как еще я могу подойти <requirement>
, чтобы правильно ввести свои свойства?