В TypeScript всяка стойност може да бъде присвоена на типа „неизвестен“, но без твърдение за тип „неизвестен“ не може да бъде присвоен на нищо друго освен на себе си
Въведение
Не толкова отдавна, във версия 3.0, TypeScript въведе нов тип unknown
към своя инструментариум, но какво прави този тип и по-конкретно кога трябва да го използваме?
Тази статия ще разгледа този нов тип, за да разбере по-добре неговата цел.
Ние също така последователно ще го сравняваме с неговия събрат, тип any
; ако все още не сте запознати с него, вижте тази статия, където сме го обсъждали по-подробно.
Какъв е неизвестният тип?
В Typescript всяка стойност може да бъде присвоена на типа unknown
, но без твърдение за тип, unknown
не може да бъде присвоено на нищо друго освен на себе си и на типа any
. По същия начин не се допускат операции върху стойност с тип, зададен като unknown
, без първо да се потвърди или ограничи до по-точен тип.
Можем да присвоим произволна стойност на променлива от тип unknown
по същия начин, както можем с променлива от тип any
. За разлика от нашия случай, не можем да имаме достъп до свойства на променливи от тип unknown
, нито да ги извикваме или конструираме.
Освен това стойности unknown
могат да се присвояват само на променливи от типовете any
и unknown
.
Присвояване на стойности на променлива от тип unknown
:
let val: unknown; val = true; // Fine val = 42; // Fine val = "hey!"; // Fine val = []; // Fine val = {}; // Fine val = Math.random; // Fine val = null; // Fine val = undefined; // Fine val = () => { console.log('Hey again!'); }; // Fine
Присвояване на стойности от различни типове на променлива от тип any
:
let val: any; val = true; // Fine val = 42; // Fine val = "hey!"; // Fine val = []; // Fine val = {}; // Fine val = Math.random; // Fine val = null; // Fine val = undefined; // Fine val = () => { console.log('Hey again!'); }; // Fine
Присвояване на стойност от тип unknown
на променливи от други типове:
let val: unknown; const val1: unknown = val; // Fine const val2: any = val; // Fine const val3: boolean = val; // Will throw error const val4: number = val; // Will throw error const val5: string = val; // Will throw error const val6: Record<string, any> = val; // Will throw error const val7: any[] = val; // Will throw error const val8: (...args: any[]) => void = val; // Will throw error
Правене на неизвестния тип по-специфичен
Можем да стесним възможните резултати от стойност от тип unknown
.
Нека да разгледаме следния пример:
const isNumbersArray = (val: unknown): val is number[] => ( Array.isArray(val) && val.every((element) => typeof element === 'number') ); const unknownValue: unknown = [12, 2, 8, 17, 14]; if (isNumbersArray(unknownValue)) { const sum = unknownValue.reduce((accumulator, currentElement) => (accumulator + currentElement) , 0); console.log(sum); }
Преди това типът беше unknown
; обаче, след като извикахме isNumbersArray
с unknownValue
като негов аргумент, заключихме, че типът на unknownValue
всъщност е този на масив от числа.
Кога ще трябва да използваме неизвестния тип?
Един конкретен сценарий, при който може да искаме да използваме типа unknown
, е когато трябва да вземем нещо от локално хранилище.
Всички елементи на localStorage
API се сериализират преди съхранение. Нашият случай на използване обаче включва стойността на извлечения елемент след десериализация.
Като използваме типа unknown
, ще можем да напишем типа на десериализирания елемент, вместо просто да използваме анотацията any
.
type ResultType = | { success: true; value: unknown } | { success: false; error: Error }; const retrieveItemFromLocalStorage = (key: string): ResultType => { const item = localStorage.getItem(key); if (!item) { // The item does not exist, thus return an error return { success: false, error: new Error(`Item with key "${key}" does not exist`), }; } let value: unknown; try { value = JSON.parse(item); } catch (error) { // The item is not a valid JSON value, thus return an error return { success: false, error, }; } // Everything's fine, thus return a successful result return { success: true, value, }; }
ResultType
е „маркиран тип обединение“ (известен също като дискриминиран тип обединение). Може да срещнете Maybe
, Option
или Optional
, които са неговия еквивалент на други езици.
Ние използваме ResultType
, за да моделираме чисто успешните или неуспешните резултати от операцията.
И ето пример за това как бихме използвали нашата функция retrieveItemFromLocalStorage
:
const result = retrieveItemFromLocalStorage("cached-blogs"); if (result.success) { // We've narrowed the `success` property to `true`, // so we can access the `value` property const cachedBlogs: unknown = result.value; if (isArrayOfBlogs(cachedBlogs)) { // We've narrowed the `unknown` type to `Array<Blog>`, // so we can safely use our cached `cachedBlogs` array as we would console.log('Cached blogs:', cachedBlogs); } } else { // We've narrowed the `success` property to `false`, // so we can access the `error` property console.error(result.error); }
Резюме
Надявам се, че сте се насладили на четенето и сте придобили малко повече представа за това какво представлява типът unknown
, което го прави различен от типа any
и кога обикновено го използваме в реални проекти.
Чувствайте се свободни да оставите вашите мисли в секцията за коментари по-долу.
наздраве!
Повече съдържание в PlainEnglish.io. Регистрирайте се за нашия безплатен седмичен бюлетин. Следвайте ни в Twitter, LinkedIn, YouTube и Discord . Интересувате ли се от Growth Hacking? Вижте Circuit.