angular - Const Obje’den eşlemeli tipler oluştur


Aşağıdaki nesneye sahibim (bu Angular yönlendirmesini/sayfalarını tanımlar. Bazılarının değiştirilebilecek parametreleri vardır.):

const ROUTES = {
  PAGE_NO_PARAMS: '/hello/page/two',
  PAGE_R: '/about/:id',
  PAGE_Z: '/page/page/:param/:id',
  PAGE_N: '/who/:x/:y/:z/page',
} as const

Yoldaki parametreleri (:xxx) göz ardı eden bir tür geçerli sayfa türünü bu nesneden bazı türde joker karakter kullanarak oluşturabilir miyim?

Yani. Aşağıdaki gibi bir tür oluşturun (ama ROUTES nesnesini kullanarak). Benimde zaten wildcard olmadan var. Ancak, parametreli yollar çözülmüş ie. /about/xxxxx type kontrolünü karşılamıyor

type ValidRoute = '/hello/page/two' | '/about/${string}' | '/page/page/${string}/${string}'| '/who/${string}/${string}/${string}/page'

Özetle, ROUTES içindeki her özelliği dolaşmak ve /:any string/ öğesini /$ {string} ile değiştiren bir tür oluşturmak istiyorum

Umarım tüm bunlar mantıklıdır. Çalışma zamanı hatalarını derleme hatalarıyla değiştirmeye çalışıyorum.

Cevap #1

Yolu işlemek için bazı özyinelemeli koşullu tipleri kullanabilirsiniz. :name ile karşılaştığımızda bunu $string} ile değiştirebiliriz

type MakeValidRoute<T extends string, R extends string = ''> =
  T extends `${infer Head}/:${infer Name}/${infer Tail}`?
    MakeValidRoute<`/${Tail}`, `${R}${Head}/${string}`>:
  T extends `${infer Head}/:${infer Name}`?
    `${R}${Head}/${string}`:
    `${R}${T}`

Oyun Alanı Bağlantısı

Bu türlerin derleyicideki performansını artırmak için kuyruk özyinelemeli koşullu türler kullanıyoruz

Cevap #2

Buradaki diğer cevap doğru. Tamamlık açısından, bunu ben şöyle yaptım:

type SubstParamNames<T extends string, S extends string = string, A extends string = ""> =
  T extends `${infer F}:${infer _}/${infer R}` ? SubstParamNames<R, S, `${A}${F}${S}/`>
  : T extends `${infer F}:${infer _}` ? `${A}${F}${S}` : `${A}${T}`

SubstParamNames<T, S> türü, kuyrukta özyinelemeli bir koşullu türdür ve T içindeki tüm iki nokta ile ayrılmış yol parçalarını (bir ":" ile başlar ve ya bir "/" ile biter ya da stringin sonuna kadar gider) S değerininyle değiştirir; S varsayılan olarak sadece stringtir.

Bu, aşağıdaki çıktıyı verir:

const ROUTES = {
  PAGE_NO_PARAMS: '/hello/page/two',
  PAGE_R: '/about/:id',
  PAGE_Z: '/page/page/:param/:id',
  PAGE_N: '/who/:x/:y/:z/page',
} as const

type Routes = SubstParamNames<typeof ROUTES[keyof typeof ROUTES]>
/* type RP = type Routes = "/hello/page/two" | `/about/${string}` | 
 `/page/page/${string}/${string}` | `/who/${string}/${string}/${string}/page`
*/

Ve eğer önemliyse, string öğesini başka bir şeyle değiştirebilirsiniz:

type IfItMatters = SubstParamNames<"/ay/:bee/cee/:dee/eee", "XXX">
// type IfItMatters = "/ay/XXX/cee/XXX/eee"

Koda yönelik oyun alanı bağlantısı