अपडेट करें:

मुझे वहाँ पहुँचाने के लिए @OliverRadini को धन्यवाद। उनकी प्रतिक्रिया के बाद मेरे पास एक समाधान है जो मेरे मामले में काम करता है। उनके उत्तर के साथ मेरे पास एकमात्र समस्या यह थी कि मुझे बाहरी रूप से टाइप करने की आवश्यकता थी जो आप फ़ंक्शन में पास कर रहे हैं, लेकिन किसी फ़ंक्शन में होने के बिना कुंजी का अनुमान लगाने का कोई तरीका नहीं समझ सका। मेरे मामले में हमारे लिए ऐसा करने के लिए उपयोग का उपयोग करना ठीक है, जैसा कि निम्नानुसार है:

interface ITest {
  n: number;
  b: boolean;
}

const f = <K extends keyof ITest>(x: { id: K; params: ITest[K] }) => ({
  ...x,
  _propToConfirmYourUsingTheUtilNeverWriteThisManually: true,
});

type Props = ReturnType<typeof f>;

const a: Props = f({ id: "n", params: 1 }); // no type error
const b: Props = f({ id: "n", params: true }); // Type 'true' is not assignable to type 'number'

const c = f({ id: "b", params: true }); // no type error
const d = f({ id: "b", params: 1 }); // Type 'number' is not assignable to type 'boolean'

// Errors because we didn't add _propToConfirmYourUsingTheUtilNeverWriteThisManually
// This ridiculously named prop should ensure we don't override it without noticing
const z: Props = {
  // Property '_propToConfirmYourUsingTheUtilNeverWriteThisManually' is missing in type ...
  id: "b",
  params: 7,
};

f(a); // no type error
f(b); // no type error
f(c); // no type error
f(d); // no type error


अपडेट करें:

इस मामले का पारित होना ठीक है:

const invalidProps1: Props<IdsWithParameters> = {
  id: "id1",
  params: {
    param1: "string",
  },
};

इसके बाहर के कोड के साथ अतिरिक्त गुण कोई समस्या नहीं है। लेकिन इस घटक फ़ंक्शन के लिए सामान्य होने और IdsWithParameters में कोई भी आईडी लेने में सक्षम होने के लिए हम स्पष्ट रूप से Props<'id1'> जैसे @oliverradini उत्तर में कुंजी निर्दिष्ट नहीं कर सकते हैं। लेकिन उनकी मदद ने मुझे यहां तक ​​पहुंचाया है जो करीब है लेकिन अभी भी काफी नहीं है।

interface Props<K extends keyof IdsWithParameters> {
  id: K;
  params: IdsWithParameters[K];
}

// Somehow want Props to know what is being used as the id and infer 
// the correct params type
function Text(props: Props) {
  const text = intlFunctionThatGetsTheTranslatedText(props.id, props.params);

  return <>{text}</>
}


मूल पद:

मैं एक पुस्तकालय का निर्माण कर रहा हूँ जहाँ मुझे लोगों को एक वस्तु (IdsWithParameters इंटरफ़ेस) बनाने की अनुमति देने की आवश्यकता है, जिसमें अनुमत कुंजियों और टाइप किए गए मापदंडों को प्रत्येक विशिष्ट कुंजी के साथ जाने की अनुमति है। विभिन्न स्थानों पर वे एक ऐसी वस्तु निर्दिष्ट करना चाहेंगे जिसमें और id और params (द प्रॉप्स इंटरफ़ेस) हों जो IdsWithParameters उदाहरण से 1 विशिष्ट कुंजी/मान युग्म से मेल खाते हों।

मैं एक लुकअप का उपयोग करके एक बिंदु पर पहुंच सकता हूं जहां आपको एक वैध कुंजी और पैरा में प्रॉप्स इंस्टेंस में पास करना होगा। लेकिन यह पता नहीं लगा सकता कि दिए गए कुंजी/आईडी से मेल खाने वाले पैरा को कैसे सीमित किया जाए।

interface IdsWithParameters {
  id1: {};
  id2: {
    param1: string;
  };
  id3: {
    param2: boolean;
    param3: number;
  };
}

interface Props<I extends IdsWithParameters> {
  id: keyof I;
  params: I[keyof I];
}

// This works as expected
const validProps1: Props<IdsWithParameters> = {
  id: "id1",
  params: {},
};

// This works as expected
const validProps2: Props<IdsWithParameters> = {
  id: "id2",
  params: {
    param1: "string",
  },
};

const invalidProps1: Props<IdsWithParameters> = {
  id: "id1",
  // Want this to error, saying that params should be {} but it passes
  params: {
    param1: "string",
  },
};

const invalidProps2: Props<IdsWithParameters> = {
  id: "id2",
  // Want this to error, saying that params should be { param1: string; } but it passes
  params: {},
};

मुझे लगता है कि मैं इसे बहुत लंबे समय से देख रहा हूं और या तो इसे करने का एक आसान तरीका है या एक बेहतर समाधान है और मैं इसे अब और नहीं देख सकता। संदर्भ के लिए मैं रिएक्ट पैकेज में अनुवाद योग्य सामग्री स्ट्रिंग को संभालने के लिए एक पैकेज बना रहा हूं। तो इसका इस्तेमाल इस तरह किया जा सकता है:

// IdsWithParameters in above example
interface ContentStringsWithAcceptableParameters {
  "errors.404.title": {},
  "errors.404.content": {
     pageUrl: string;
  },
  "errors.retryAttemptsLeft": {
    attemptsLeft: number;
  }
}

interface Props<I extends ContentStringsWithAcceptableParameters> {
  id: keyof I;
  params: I[keyof I];
}

// The react component we'll be using
function Text(props: Props<ContentStringsWithAcceptableParameters>) {
  const text = intlFunctionThatGetsTheTranslatedText(props.id, props.params);

  return <>{text}</>
}
0
Charlie Jackson 8 जून 2020, 13:20

1 उत्तर

सबसे बढ़िया उत्तर

मुझे लगता है कि हम समझ सकते हैं कि हम क्या करने की कोशिश कर रहे हैं यदि हम उदाहरण को थोड़ा सरल करते हैं:

interface ITest {
  n: number;
  b: boolean;
}

const f = <K extends keyof ITest>(
  x: {
    id: K,
    params: ITest[K],
  },
) => true;

f({ id: 'n', params: 1 });    // no type error
f({ id: 'n', params: true }); // Type 'true' is not assignable to type 'number'

f({ id: 'b', params: true }); // no type error
f({ id: 'b', params: 1 });    // Type 'number' is not assignable to type 'boolean'

हम निर्दिष्ट कर सकते हैं कि कुछ सामान्य (K ऊपर के उदाहरण में) प्रकार की एक कुंजी का विस्तार करते हैं। फिर हम उस कुंजी का उपयोग उस प्रकार को प्राप्त करने के लिए कर सकते हैं जिसे हम ढूंढ रहे हैं।

1
OliverRadini 8 जून 2020, 18:06