برنامه نویسی

TS: امضاهای شاخص سطح بعدی در داخل رابط ها و انواع

با Typescript می‌توانیم رابط‌های خود را در مورد اینکه چه نوع ویژگی‌هایی را می‌پذیرد، انعطاف‌پذیر کنیم. ممکن است بپرسید چرا این مفید است، خوب موقعیت‌های مختلفی وجود دارد که ما باید کامپایلر TS را به گونه‌ای تعریف کنیم که به جز ویژگی‌هایی که در رابط تعریف شده است، برای سایر ویژگی‌ها بازتر باشد. این موارد شامل اما نه محدود به موارد زیر است:

  • اینترفیس دارای خصوصیات بیشتری نسبت به تعریف معقول خواهد بود.
  • ما قصد داریم از طریق علامت گذاری براکت به خصوصیات به صورت پویا دسترسی داشته باشیم myObj[value].

بنابراین بیایید نگاهی بیندازیم که چگونه می توان این کار را انجام داد

interface Pet {
  // allows any property value of type string
  // what if we want more control over possible properties
  [key: string]: string
}

const myPet: Pet = {
  // all valid values
  // what if we have a general rule about our props naming convention?
  foo: 'foo',
  bar: 'bar',
  kbgyb: '??'
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این رویکرد ممکن است کمی بیش از حد انعطاف پذیر باشد و ما الگویی داریم که ویژگی های ما به نظر می رسد

interface Pet {
  // by adding the prefix 'content-' we can lock down part of the props name
  [key: `content-${string}`]: string
}

const myPet: Pet = {
  'content-type': 'foo', // valid property name
  two: 'bar' // invalid property name as it is not prefixed with 'content-'
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اجازه دهید این یک گام دیگر را جلوتر ببریم و مقادیر مختلفی را که رابط / نوع ما می تواند بپذیرد تعریف کنیم.

type StringProps = 'type' | 'name' | 'breed';
type StringPet { [key in StringProps]: string }

// same as this 
interface StringPet {
  type: string;
  name: string;
  breed: string;
}

const myPet: Pet = {
  type: 'foo', // valid property name
  two: 'bar' // invalid property name
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با استفاده از StringProps همچنین می توانیم بدون نیاز به نوشتن، رابط را از 5 خط کد به 2 خط کاهش دهیم string 3 بار هم همینطور این رویکرد را می توان حتی بیشتر گسترش داد:

type StringProps = 'type' | 'name' | 'breed' | 'eyeColor';
type StringPet { [key in StringProps]: string }

type IntProps = 'age' | 'weight' | 'legs';
type IntPet { [key in IntProps]: number }

type BoolProps = 'wings' | 'claws' | 'fur';
type BoolPet { [key in BoolProps]: boolean }

// here we intersect two types together into one
// note: types are intersected, not extended like interfaces are
type WholePet = IntPet & StringPet & BoolPet;

// WholePet in the more verbose view looks like this
interface WholePet {
  type: string;
  name: string;
  breed: string;
  eyeColor: string;
  age: number;
  weight: number;
  legs: number;
  wings: boolean;
  claws: boolean;
  fur: boolean;
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

رویکرد فوق نه تنها کنترل امضای فهرست را به ارمغان می آورد، بلکه می تواند برای مقیاس پذیرتر کردن رابط ها و انواع ما نیز مورد استفاده قرار گیرد. ما مجبور نیستیم خودمان را با انواع بدوی مانند string، number، یا boolean.

اگر بخواهیم نوع اولیه را برای یکی از خصوصیات خود تغییر دهیم، به سادگی آن را به نوع Prop مناسب مانند from منتقل می کنیم IntProps به StringProps.

با تشکر برای خواندن!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

همچنین ببینید
بستن
دکمه بازگشت به بالا