टाइपस्क्रिप्ट d.ts फ़ाइल में परिभाषित इंटरफ़ेस प्रॉपर्टी प्रकार


126

क्या *.d.tsटाइपस्क्रिप्ट में इंटरफ़ेस संपत्ति के प्रकार को बदलने का एक तरीका है ?

उदाहरण के लिए: एक इंटरफ़ेस के x.d.tsरूप में परिभाषित किया गया है

interface A {
  property: number;
}

मैं इसे टाइपस्क्रिप्ट फ़ाइलों में बदलना चाहता हूं जो मैं लिखता हूं

interface A {
  property: Object;
}

या यहां तक ​​कि यह काम करेगा

interface B extends A {
  property: Object;
}

क्या यह काम करेगा? जब मैंने अपने सिस्टम पर कोशिश की तो यह काम नहीं किया। बस पुष्टि करना चाहते हैं कि क्या यह संभव है?

जवाबों:


56

आप किसी मौजूदा प्रॉपर्टी का प्रकार नहीं बदल सकते।

आप एक संपत्ति जोड़ सकते हैं:

interface A {
    newProperty: any;
}

लेकिन मौजूदा एक प्रकार को बदलना:

interface A {
    property: any;
}

एक त्रुटि के परिणाम:

बाद में परिवर्तनशील घोषणाओं में एक ही प्रकार होना चाहिए। परिवर्तनीय 'गुण' प्रकार 'संख्या' का होना चाहिए, लेकिन यहां 'कोई भी' प्रकार है

आप निश्चित रूप से अपना स्वयं का इंटरफ़ेस रख सकते हैं जो किसी मौजूदा को बढ़ाता है। उस स्थिति में, आप किसी प्रकार को केवल संगत प्रकार से ओवरराइड कर सकते हैं, उदाहरण के लिए:

interface A {
    x: string | number;
}

interface B extends A {
    x: number;
}

वैसे, आपको संभवतः Objectएक प्रकार के रूप में उपयोग करने से बचना चाहिए , इसके बजाय प्रकार का उपयोग करें any

में लिये दस्तावेज anyप्रकार यह कहा गया है:

किसी भी प्रकार के मौजूदा जावास्क्रिप्ट के साथ काम करने का एक शक्तिशाली तरीका है, जो आपको संकलन के दौरान धीरे-धीरे ऑप्ट-इन और ऑप्ट-आउट करने की अनुमति देता है। आप ऑब्जेक्ट को एक समान भूमिका निभाने की उम्मीद कर सकते हैं, जैसा कि अन्य भाषाओं में है। लेकिन प्रकार ऑब्जेक्ट के चर केवल आपको उनके लिए कोई भी मूल्य प्रदान करने की अनुमति देते हैं - आप उन पर मनमाने तरीके से कॉल नहीं कर सकते हैं, यहां तक ​​कि जो वास्तव में मौजूद हैं :

let notSure: any = 4;
notSure.ifItExists(); // okay, ifItExists might exist at runtime
notSure.toFixed(); // okay, toFixed exists (but the compiler doesn't check)

let prettySure: Object = 4;
prettySure.toFixed(); // Error: Property 'toFixed' doesn't exist on type 'Object'.

टाइपस्क्रिप्ट> = 1.1 के साथ इंटरफेस के प्रकार को ओवरराइट करने के लिए, आपको मूल इंटरफ़ेस से सभी विधियों को शामिल करने की आवश्यकता है, अन्यथा आपको त्रुटि मिलेगी कि प्रकार असंगत रूप से देखे जा रहे हैं github.com/Microsoft/TypeScript/issues/978
jcubic

आप उन मूल्यों को स्वीकार कर सकते हैं जिन्हें आप पहले लिखना चाहते हैं, फिर उन्हें फिर से परिभाषित करें, क्या हम @ZSkycat को हल करने के उत्तर दे सकते हैं?
zeachco

जावा को 'अन्य भाषाओं' के रूप में संदर्भित करने के लिए डाउनवोट
wvdz

@ wvdz यह नहीं है कि मैं गिरावट के बारे में बहुत परवाह करता हूं, लेकिन आप किस बारे में बात कर रहे हैं? किसी ने भी जावा को कहां भेजा? "जावा" के पेज को खोजने के लिए केवल एक खोज है और यह आपकी टिप्पणी में है।
नित्ज़न तोमर

शायद मैं थोड़ा गदगद था लेकिन इसने मुझे थोड़ा नाराज कर दिया कि आपने "अन्य भाषाएं" तब कही थीं जब आप जावा की तरह कह सकते थे। या वास्तव में बहुत सी अन्य भाषाएं हैं जिनका सार्वभौमिक आधार वर्ग के रूप में वस्तु है? मुझे C # का पता है, लेकिन निश्चित रूप से C # जावा से काफी प्रेरित था।
wvdz

226

मैं एक विधि का उपयोग करता हूं जो पहले खेतों को छानती है और फिर उन्हें जोड़ती है।

संदर्भ प्रकार से संपत्ति को छोड़ दें

interface A {
    x: string
}

export type B = Omit<A, 'x'> & { x: number };

इंटरफ़ेस के लिए:

interface A {
    x: string
}

interface B extends Omit<A, 'x'> {
  x: number
}

3
यह जानकर बहुत अच्छा लगा। लेकिन समस्या यह है कि यह अभी भी मौजूदा को संशोधित नहीं कर रहा है।
फ्रीविंड

10
यह ठीक वही है जिसकी मुझे तलाश थी। यह मैं कैसे extendडिफ़ॉल्ट रूप से काम करने के लिए टाइपस्क्रिप्ट की उम्मीद है , लेकिन अफसोस, यह थोड़ा Omitसब कुछ ठीक करता है expected
डावसन बी

1
इंटरफ़ेस का विस्तार वास्तव में मैं क्या देख रहा था, धन्यवाद!
एमएच

1
नोट: इसका उपयोग करने के लिए आपको ऊपर 3.5.3 टाइपस्क्रिप्ट की आवश्यकता होगी।
विक्सन 2

92
type ModifiedType = Modify<OriginalType, {
  a: number;
  b: number;
}>

interface ModifiedInterface extends Modify<OriginalType, {
  a: number;
  b: number;
}> {}

ZSkycat के extends Omit समाधान से प्रेरित होकर , मैं इसके साथ आया:

type Modify<T, R> = Omit<T, keyof R> & R;

// before typescript@3.5
type Modify<T, R> = Pick<T, Exclude<keyof T, keyof R>> & R

उदाहरण:

interface OriginalInterface {
  a: string;
  b: boolean;
  c: number;
}

type ModifiedType  = Modify<OriginalInterface , {
  a: number;
  b: number;
}>

// ModifiedType = { a: number; b: number; c: number; }

कदम दर कदम:

type R0 = Omit<OriginalType, 'a' | 'b'>        // { c: number; }
type R1 = R0 & {a: number, b: number }         // { a: number; b: number; c: number; }

type T0 = Exclude<'a' | 'b' | 'c' , 'a' | 'b'> // 'c'
type T1 = Pick<OriginalType, T0>               // { c: number; }
type T2 = T1 & {a: number, b: number }         // { a: number; b: number; c: number; }

टाइपस्क्रिप्ट उपयोगिता प्रकार


9
यह एक बेहतरीन उपाय है।
ऑस्टिन ब्रुंकहर्स्ट

1
यहाँ Noob, लेकिन आप अपने उदाहरण नहीं में एक अंतरफलक से एक प्रकार में बदल रहे हैं? या कोई अंतर नहीं है?
डोमिनिक

नाइसिफेई: डी
सामीकोओ

1
@ प्रमुख अच्छा बिंदु, मैंने उत्तर अपडेट कर दिया है। एक ही नाम वाले दो इंटरफेसेस विलय कर सकते हैं। typecriptlang.org/docs/handbook/…
Qwerty

33

@ ZSkycat के उत्तर को थोड़ा बढ़ाते हुए, आप एक जेनेरिक बना सकते हैं जो दो ऑब्जेक्ट प्रकारों को स्वीकार करता है और पहले के सदस्यों को ओवरराइड करने वाले दूसरे सदस्यों के साथ एक विलय प्रकार देता है।

type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>
type Merge<M, N> = Omit<M, Extract<keyof M, keyof N>> & N;

interface A {
    name: string;
    color?: string;
}

// redefine name to be string | number
type B = Merge<A, {
    name: string | number;
    favorite?: boolean;
}>;

let one: A = {
    name: 'asdf',
    color: 'blue'
};

// A can become B because the types are all compatible
let two: B = one;

let three: B = {
    name: 1
};

three.name = 'Bee';
three.favorite = true;
three.color = 'green';

// B cannot become A because the type of name (string | number) isn't compatible
// with A even though the value is a string
// Error: Type {...} is not assignable to type A
let four: A = three;

1
बहुत अच्छा :-) मैंने इसे ओमिट के साथ एक या दो गुणों के साथ पहले किया है, लेकिन यह बहुत कूलर है :-) मैं अक्सर एक सर्वर इकाई प्रकार का विस्तार करना चाहता हूं और क्लाइंट पर आवश्यक या वैकल्पिक होने के लिए कुछ चीजें बदल देता हूं। ।
सिमोन_विवर

1
यह अब स्वीकृत समाधान होना चाहिए। एक इंटरफ़ेस को "विस्तारित" करने का सबसे साफ तरीका।
मनुहूर्त

10

Omit इंटरफ़ेस का विस्तार करते समय संपत्ति:

interface A {
  a: number;
  b: number;
}

interface B extends Omit<A, 'a'> {
  a: boolean;
}

3

यह हास्यास्पद है कि मैं उसी मामले को हल करने की संभावना की जांच करने में दिन बिताता हूं। मैंने पाया कि ऐसा करना संभव नहीं है:

// a.ts - module
export interface A {
    x: string | any;
}

// b.ts - module
import {A} from './a';

type SomeOtherType = {
  coolStuff: number
}

interface B extends A {
    x: SomeOtherType;
}

कारण आपके एप्लिकेशन में सभी उपलब्ध प्रकारों के बारे में एक मॉड्यूल को नहीं पता हो सकता है। और यह हर जगह से काफी उबाऊ बंदरगाह है और इस तरह कोड कर रहा है।

export interface A {
    x: A | B | C | D ... Million Types Later
}

आपको स्व-पूर्ण कार्यों को अच्छी तरह से करने के लिए बाद में परिभाषित करना होगा।


तो आप थोड़ा धोखा दे सकते हैं:

// a.ts - module
export interface A {
    x: string;
}

कुछ प्रकारों को डिफ़ॉल्ट रूप से छोड़ दें, जब आवश्यक न होने पर स्वत: पूर्ण कार्य करने की अनुमति दें।

फिर

// b.ts - module
import {A} from './a';

type SomeOtherType = {
  coolStuff: number
}

// @ts-ignore
interface B extends A {
    x: SomeOtherType;
}

@ts-ignoreध्वज का उपयोग करते हुए मूर्खतापूर्ण अपवाद को अक्षम करें , यह कहते हुए कि हम कुछ गलत कर रहे हैं। और मजेदार चीज सब कुछ उम्मीद के मुताबिक काम करती है।

मेरे मामले में मैं प्रकार की गुंजाइश दृष्टि को कम कर रहा हूं x, इसकी अनुमति मुझे कोड को और अधिक सख्त करने की अनुमति देती है। उदाहरण के लिए, आपके पास 100 गुणों की सूची है, और आप बेवकूफ स्थितियों से बचने के लिए इसे 10 तक कम कर देते हैं


3

संपत्ति के प्रकार को कम करने के लिए, सरल extendकाम सही है, जैसा कि निट्ज़ैन के जवाब में है :

interface A {
    x: string | number;
}

interface B extends A {
    x: number;
}

चौड़ीकरण के लिए, या आम तौर पर ओवरराइड करने के लिए, आप Zskycat का समाधान कर सकते हैं :

interface A {
    x: string
}

export type B = Omit<A, 'x'> & { x: number };

लेकिन, यदि आपका इंटरफ़ेस Aसामान्य इंटरफ़ेस का विस्तार कर रहा है, तो आप Aउपयोग करते समय कस्टम प्रकार के शेष गुणों को खो देंगे Omit

जैसे

interface A extends Record<string | number, number | string | boolean> {
    x: string;
    y: boolean;
}

export type B = Omit<A, 'x'> & { x: number };

let b: B = { x: 2, y: "hi" }; // no error on b.y! 

कारण है, Omitआंतरिक रूप से केवल Exclude<keyof A, 'x'>उन चाबियों से अधिक है जो string | numberहमारे मामले में सामान्य होंगे । तो, Bबन जाएगा {x: number; }और के प्रकार के साथ किसी भी अतिरिक्त संपत्ति को स्वीकार करता है number | string | boolean


इसे ठीक करने के लिए, मैं OverridePropsनिम्नलिखित के साथ एक अलग उपयोगिता प्रकार के साथ आया :

type OverrideProps<M, N> = { [P in keyof M]: P extends keyof N ? N[P] : M[P] };

उदाहरण:

type OverrideProps<M, N> = { [P in keyof M]: P extends keyof N ? N[P] : M[P] };

interface A extends Record<string | number, number | string | boolean> {
    x: string;
    y: boolean;
}

export type B = OverrideProps<A, { x: number }>;

let b: B = { x: 2, y: "hi" }; // error: b.y should be boolean!

1

यदि किसी और को ऐसा करने के लिए सामान्य उपयोगिता प्रकार की आवश्यकता है, तो मैं निम्नलिखित समाधान के साथ आया:

/**
 * Returns object T, but with T[K] overridden to type U.
 * @example
 * type MyObject = { a: number, b: string }
 * OverrideProperty<MyObject, "a", string> // returns { a: string, b: string }
 */
export type OverrideProperty<T, K extends keyof T, U> = Omit<T, K> & { [P in keyof Pick<T, K>]: U };

मुझे इसकी आवश्यकता थी क्योंकि मेरे मामले में, ओवरराइड करने की कुंजी एक सामान्य थी।

यदि आपके पास Omitतैयार नहीं है , तो संपत्ति को प्रकार से बाहर निकालें देखें ।


1
यह वही है जो मैं देख रहा था, मैं आपको पर्याप्त धन्यवाद नहीं दे सकता: D: D: D
dwoodwardgb

@dwoodwardgb को खुशी हुई कि यह किसी और के लिए उपयोगी था :-)
टोनी

0

नोट: निश्चित नहीं कि यदि इस उत्तर में मैं जिस वाक्यविन्यास का उपयोग कर रहा हूं वह उपलब्ध था जब पुराने उत्तर लिखे गए थे, लेकिन मुझे लगता है कि इस प्रश्न में उल्लिखित उदाहरण को हल करने के तरीके के बारे में यह एक बेहतर तरीका है।


मेरे पास इस विषय से संबंधित कुछ समस्याएँ हैं (इंटरफ़ेस गुण ओवरराइटिंग), और यह है कि मैं इसे कैसे संभाल रहा हूँ:

  1. पहले एक जेनेरिक इंटरफ़ेस बनाएं, जिन संभावित प्रकारों का आप उपयोग करना चाहते हैं।

आप defaultजेनेरिक पैरामीटर के लिए एक मूल्य चुन सकते हैं जैसा कि आप देख सकते हैं<T extends number | SOME_OBJECT = number>

type SOME_OBJECT = { foo: "bar" }

interface INTERFACE_A <T extends number | SOME_OBJECT = number> {
  property: T;
}
  1. फिर आप उस अनुबंध के आधार पर नए प्रकार बना सकते हैं, जेनेरिक पैरामीटर के लिए एक मान पारित करके (या इसे छोड़ दें और डिफ़ॉल्ट का उपयोग करें):
type A_NUMBER = INTERFACE_A;                   // USES THE default = number TYPE. SAME AS INTERFACE_A<number>
type A_SOME_OBJECT = INTERFACE_A<SOME_OBJECT>  // MAKES { property: SOME_OBJECT }

और यह परिणाम है:

const aNumber: A_NUMBER = {
    property: 111  // THIS EXPECTS A NUMBER
}

const anObject: A_SOME_OBJECT = {
    property: {   // THIS EXPECTS SOME_OBJECT
        foo: "bar"
    }
}

खेल का मैदान टाइप करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.