javascript - Bu iki "extends" ifadesi arasındaki fark nedir?


nVal1 tipinin her konumda nasıl çıkarılabildiğini, nVal2 için neden yapılamadığını anlayamıyorum.

function rSelf1<T extends unknown[] | [unknown]>(vs: T): T {
  return vs;
}

function rSelf2<T extends unknown[]>(vs: T): T {
  return vs;
}

const nVal1 = rSelf1(["a", 1, 2, true]);
const nVal2 = rSelf2(["a", 1, 2, true]);

kod bağlantısı: https://codesandbox.io/s/typescript-playground-export-forked-t1d8o?file=/index.ts

Cevap #1

(A whole bunch of idk the answer but here's some digging I did to maybe give you some context and related info)

Bu hem beni şaşırtıyor hem de heyecanlandırıyor. Temelde bana "unknown[] | [unknown]" ifadesinin tuple (demet) çıkarsamak için kullanılabileceğini fark ettirdi. Bunu hep yapmak istemiştim. Bu biraz hileli görünüyor ve bunun nasıl çalıştığını çözemedim. Tuple için bu ts-essentials tipini buldum. Sonra biraz daha araştırma yaptım ve bunun nasıl çalıştığını açıklayan bu GitHub yanıtını buldum. Bu bize biraz yardımcı oluyor. Artık "unknown[] | [unknown]" ifadesinin derleyiciyi tuple tipini çıkarmaya zorladığını biliyoruz. Ama neden? Henüz bunu bilmiyorum. Bu davranışı açıklayan bir şey bulamıyorum.

Bunu araştırmadan önceki düşüncem. Yani sorunuza doğrudan cevap veremem, ama bunu ilgili bir StackOverflow gönderisinde gördüm. Tuple türlerini kolayca çıkarsamak için rest parametrelerini kullanabilirsiniz. Bu yöntemi seviyorum çünkü TypeScript oluşturucularının bunu amaçladığı görünüyor. Ama bu, çalışma zamanında fazladan kod ekliyor ve bu iyi değil.

Bunu yapmak için başka bir yol (çözüm 2) buldum, ama yine de tamamen doğru bir çözüm değil. Bununla, fonksiyonun kullanıcılarının dizi üzerinde 'as const' yapmalarını gerektiriyor.

// solution 1
function tuple<T extends unknown[]>(...v: T) {
  return v;
}
function rSelf3<T>(vs: T): T {
  return vs;
}
const nVal3 = rSelf3(tuple("a", 1, true));

// solution 2
type Writable<T> = { -readonly [P in keyof T]: T[P] };
function rSelf4<T extends readonly unknown[]>(vs: T): Writable<T> {
  return vs;
}
const nVal4 = rSelf4(["a", 1, true] as const);