beta

4.9

Оператор satisfies

При отсутствии явной аннотации типа для объекта созданного с помощью литерала объекта

При инициализации объекта без явного указания аннотации типа у вывода типа не возникает никаких проблем.

ts
const colors = { red: [255,0,0], green: `#00ff00`, blue: [0,0,255] }; // { red: number[]; green: string; blue: number[]; }

К сожалению, аналогичное утверждение не применимо к разработчикам. Никто не застрахован от случайной опечатки допущенной, например, в названии поля объекта.

ts
const colors = { reed: [255,0,0], // reed вместо red green: `#00ff00`, blue: [0,0,255] };

Решение в виде явного перечисления типов полей и ассоциированных с ними значений не решает проблему, поскольку в смешанных объектных типах не понятно, какое поле с каким конкретным типом связанно, что на практики делает невозможным взаимодействие без явного приведения типа.

ts
type ColorsKey = `red`|`green`|`blue`; type RGB = [red: number, green: number, blue: number]; const colors: Record<ColorsKey, string | RGB> = { red: [255,0,0], green: `#00ff00`, blue: [0,0,255] } ; /** * опечатка именования поля объекта уже не возможна, но тип для каждого поля выводится на основе общих для всех членов. */ colors.red // (property) red: string | RGB (Хотя массив!) colors.green // (property) red: string | RGB (Хотя строка!)

Для разрешения этой ситуации и был создан оператор satisfies намекающий выводу типов на особый способ при выполнении его работы.

ts
type ColorsKey = `red`|`green`|`blue`; type RGB = [red: number, green: number, blue: number]; const colors = { red: [255,0,0], green: `#00ff00`, blue: [0,0,255] } satisfies Record<ColorsKey, string | RGB>; colors.red // (property) red: [number, number, number] colors.green // (property) green: string

Единственный момент на который стоит обратить внимание, что данный оператор указывается при явном утверждении,а не в области аннотации. Другими словами, его стоит воспринимать так же, как оператор явного приведения as.

Улучшение работы оператора in

Приставьте ситуацию при которой требуется обратится к возможно отсутствующему члену объекта с неизвестным типом. До этого момента, на это требовалось не мало усилий в лице явного приведения, поскольку при выявлении наличия члена по идентификаторы с помощью оператора in никак не сказывалось на типе проверяемого объекта.

ts
interface Context { package: unknown; } function getPackageName(context: Context) { const pkg = context.package; /** * [*] Error -> Property 'name' does not exist on type 'object'.ts(2339) */ if (pkg && typeof pkg === "object") { if ("name" in pkg && typeof pkg.name /** [*] */ === "string") { return pkg.name /** [*] */; } } return undefined; }

Начиная с текущей версии результаты полученные при работе оператора in берутся в расчет при рассмотрении типа объекта к которому он применялся. То есть, предыдущий пример будет отработан ожидаемым образом.

Ужесточение проверок на NaN

Поскольку результаты логических выражений на равенство\неравенство со значением NaN способны ввести в заблуждение...

ts
console.log(NaN === NaN); // false console.log(NaN !== NaN); // true

...начиная с текущей версии компилятор TypeScript вызывает ошибку при их обнаружении.

ts
function isNumberValue(value: number){ /** * [*] Ok до текущей версии и Error отсчитывая от нее -> * * This condition will always return 'true'.ts(2845) * Did you mean '!Number.isNaN(value)'? */ return value !== NaN; // [*] }