टाइपस्क्रिप्ट: टाइप 'स्ट्रिंग' के पैरामीटर के साथ कोई इंडेक्स हस्ताक्षर टाइप '{"ए" पर नहीं पाया गया: स्ट्रिंग; }


87

मेरे पास कुछ वेनिला जावास्क्रिप्ट कोड है जो एक स्ट्रिंग इनपुट लेता है, स्ट्रिंग को वर्णों में विभाजित करता है, और फिर उन वर्णों को एक वस्तु पर एक कुंजी से जोड़ता है।

DNATranscriber = {
    "G":"C",
    "C": "G",
    "T": "A",
    "A": "U"
}
function toRna(sequence){
    const sequenceArray = [...sequence];
    const transcriptionArray = sequenceArray.map(character =>{
        return this.DNATranscriber[character];
    });

    return transcriptionArray.join("");
}

console.log(toRna("ACGTGGTCTTAA")); //Returns UGCACCAGAAUU

यह उम्मीद के मुताबिक काम करता है। अब मैं इसे टाइपस्क्रिप्ट में बदलना चाहता हूं।

class Transcriptor {
    DNATranscriber = {
       G:"C",
       C: "G",
       T: "A",
       A: "U"
    }
    toRna(sequence: string) {
        const sequenceArray = [...sequence];
        const transcriptionArray = sequenceArray.map(character =>{
            return this.DNATranscriber[character];
        });
    }
}

export default Transcriptor

लेकिन मुझे निम्नलिखित त्रुटि मिल रही है।

तत्व का स्पष्ट रूप से एक 'कोई' प्रकार है क्योंकि 'स्ट्रिंग' प्रकार की अभिव्यक्ति का उपयोग अनुक्रमणिका प्रकार '{"ए" के लिए नहीं किया जा सकता है: स्ट्रिंग; } '। टाइप> 'स्ट्रिंग' के पैरामीटर के साथ कोई इंडेक्स सिग्नेचर टाइप नहीं मिला> '{"ए": स्ट्रिंग; } '। ts (7053)

मुझे लगा कि मुद्दा यह था कि मुझे एक स्ट्रिंग होने के लिए अपनी ऑब्जेक्ट कुंजी की आवश्यकता थी। लेकिन उन्हें तार में परिवर्तित करने से काम नहीं चला।

DNATranscriber = {
       "G":"C",
       "C": "G",
       "T": "A",
       "A": "U"
    }

मैं इससे काफी भ्रमित हूं। इसमें कहा गया है कि एक प्रकार का स्ट्रिंग वाला कोई सूचकांक हस्ताक्षर मेरी वस्तु पर मौजूद नहीं है। लेकिन मुझे यकीन है कि यह करता है। मैं क्या गलत कर रहा हूं?

संपादित करें - मैंने इसे DNATranscriber ऑब्जेक्ट को किसी भी प्रकार का हल देकर हल किया है।

DNATranscriber: any = {
    "G":"C",
    "C":"G",
    "T":"A",
    "A":"U"
}

इसका उत्तर नहीं है, लेकिन आप मान से लौटना भूल गएtoRna
— रेजा

आपका टाइपस्क्रिप्ट संस्करण क्या है? मुझे कोई त्रुटि नहीं है stackblitz.com/edit/angular-kupcve `
— रेजा

यह संस्करण "2.5.3" है
— इनरनेट

50
ज़रूर, कुछ टाइप करें anyऔर इसे ठीक कर देंगे, उसी तरह जैसे कि बैटरी को स्मोक डिटेक्टर से बाहर निकालना एक संभावित आग को ठीक करता है।
— jcalz

1
आउच, तुमने मुझे सही रूपक में मारा। वैसे भी, इस कैसे मैं यह कर होता है
— jcalz

जवाबों:


50

आप अपने इनपुट को मान्य करके त्रुटियों को ठीक कर सकते हैं, जो कुछ ऐसा है जिसे आपको निश्चित रूप से करना चाहिए।

निम्न रख-रखाव सही ढंग से, प्रकार की सुरक्षा मान्यताओं के माध्यम से

const DNATranscriber = {
    G: 'C',
    C: 'G',
    T: 'A',
    A: 'U'
};
export default class Transcriptor {
    toRna(sequence: string) {
        const sequenceArray = [...sequence];
        if (!isValidSequence(sequenceArray)) {
            throw Error('invalid sequence');
        }
        const transcribedRNA = sequenceArray.map(codon => DNATranscriber[codon]);
        return transcribedRNA;
    }
}

function isValidSequence(codons: string[]): codons is Array<keyof typeof DNATranscriber> {
    return codons.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
    return value in DNATranscriber;
}

यहाँ एक अधिक मुहावरेदार संस्करण है

enum DNATranscriber {
    G = 'C',
    C = 'G',
    T = 'A',
    A = 'U'
}
export default function toRna(sequence: string) {
    const sequenceArray = [...sequence];
    if (!isValidSequence(sequenceArray)) {
        throw Error('invalid sequence');
    }
    const transcribedRNA = sequenceArray.map(codon => DNATranscriber[codon]);
    return transcribedRNA;
}

function isValidSequence(values: string[]): codons is Array<keyof typeof DNATranscriber> {
    return values.every(isValidCodon);
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
    return value in DNATranscriber;
}

ध्यान दें कि हम स्पष्टता में सुधार करने और बेस जोड़ी मैपिंग के मजबूत टाइपिंग हासिल करने के लिए टाइपस्क्रिप्ट स्ट्रिंग एन्यूमरेशन का लाभ कैसे उठाते हैं। इससे भी महत्वपूर्ण बात, नोटिस करें कि हम कैसे उपयोग करते हैं function। यह महत्वपूर्ण है! जावास्क्रिप्ट को टाइपस्क्रिप्ट में परिवर्तित करने का कक्षाओं के साथ कोई लेना-देना नहीं है, इसे स्थैतिक प्रकारों के साथ करना है।

अपडेट :

टाइपस्क्रिप्ट 3.7 के बाद से, हम इसे और अधिक स्पष्ट रूप से लिख सकते हैं, इनपुट सत्यापन के बीच पत्राचार को औपचारिक रूप दे सकते हैं और मुखर हस्ताक्षर का उपयोग करके इसके प्रकार निहितार्थ कर सकते हैं ।

enum DNATranscriber {
    G = 'C',
    C = 'G',
    T = 'A',
    A = 'U'
}
export default function toRna(sequence: string) {
    const sequenceArray = [...sequence];
    validateSequence(sequenceArray);
    const transcribedRNA = sequenceArray.map(codon => DNATranscriber[codon]);
    return transcribedRNA;
}

function validateSequence(values: string[]): asserts codons is Array<keyof typeof DNATranscriber> {
    if (!values.every(isValidCodon)) {
        throw Error('invalid sequence');    
    }
}
function isValidCodon(value: string): value is keyof typeof DNATranscriber {
    return value in DNATranscriber;
}

आप के बारे में अधिक पढ़ सकते हैं अभिकथन हस्ताक्षर में टाइपप्रति 3.7 रिलीज नोट्स ।


1
एक विकल्प के रूप में, क्या एक सूचकांक हस्ताक्षर को जोड़ना संभव है DNATranscriber? चूंकि त्रुटि कहती है "Typescript: No index signature with a parameter of type 'string' was found on type '{ “A”: string; }", इसका तात्पर्य है कि टाइप 'स्ट्रिंग' के एक इंडेक्स हस्ताक्षर को जोड़ने का एक तरीका है। क्या यह किया जा सकता है?
— कैमरन हडसन

हाँ, आप ऐसा कर सकते हैं, लेकिन फिर कोड उस प्रकार सुरक्षित या अभिव्यंजक नहीं होगा जिस तरह से प्रश्न का इरादा था। एक कारण है कि उन्होंने इसे इस तरह से नहीं लिखा, एक अच्छा कारण।
— एलुआन हद्दाद

validateSequence ...:आप के rhs पर लिखते हैं codonsलेकिन पैरामीटर नाम है values। आम तौर पर एक समस्या नहीं है पहले से ही अप्रत्यक्ष के पर्याप्त स्तर हैं ...
— क्रेग हिक्स

76

इसके अलावा, आप यह कर सकते हैं:

(this.DNATranscriber as any)[character];

संपादित करें।

यह अत्यधिक अनुशंसा की जाती है कि आप ऑब्जेक्ट को इसके बजाय उचित प्रकार के साथ कास्ट करें any। किसी ऑब्जेक्ट को कास्टिंग करना anyकेवल टाइप टाइप को संकलित करने में आपको त्रुटियों से बचने में मदद करता है, लेकिन यह आपके कोड को सुरक्षित रखने में आपकी मदद नहीं करता है।

उदाहरण के लिए

interface DNA {
    G:"C",
    C: "G",
    T: "A",
    A: "U"
}

और फिर आपने इसे इस तरह डाला:

(this.DNATranscriber as DNA)[character];

1
अरे मैंने वही किया जो आपने अपने संपादन संस्करण में कहा था। लेकिन फिर भी त्रुटि हुई
— Archsx

1
एक स्पष्ट DNAप्रकार एक बुरा विचार नहीं है, लेकिन this.DNATranscriberफिर DNATranscriber: DNA"कास्ट" को बेमानी बनाने की तरह घोषित नहीं किया जाएगा ?
— अलुआन हदद


12

कोई उपयोग न करें, जेनरिक का उपयोग करें

// bad
const _getKeyValue = (key: string) => (obj: object) => obj[key];
    
// better
const _getKeyValue_ = (key: string) => (obj: Record<string, any>) => obj[key];
    
// best
const getKeyValue = <T extends object, U extends keyof T>(key: U) => (obj: T) =>
      obj[key];

ख़राब - त्रुटि का कारण यह है कि objectडिफ़ॉल्ट रूप से प्रकार केवल एक खाली वस्तु है। इसलिए एक stringप्रकार का अनुक्रमणिका का उपयोग करना संभव नहीं है {}।

बेहतर - कारण गायब हो जाता है क्योंकि अब हम संकलक को बता रहे हैं कि objतर्क स्ट्रिंग / मान ( string/any) जोड़े का संग्रह होगा । हालाँकि, हम इसका उपयोग कर रहे हैंany प्रकार , इसलिए हम बेहतर कर सकते हैं।

श्रेष्ठ - Tखाली वस्तु का विस्तार। Uकी चाबी निकालता है T। इसलिए Uहमेशा मौजूद रहेगा T, इसलिए इसे लुक अप मूल्य के रूप में इस्तेमाल किया जा सकता है।

यहाँ एक पूर्ण उदाहरण है:

मैंने जेनरिक के क्रम को बदल दिया है ( U extends keyof Tअब पहले आता है T extends object) यह उजागर करने के लिए कि जेनेरिक का आदेश महत्वपूर्ण नहीं है और आपको एक ऐसे आदेश का चयन करना चाहिए जो आपके कार्य के लिए सबसे अधिक समझ में आता है।

const getKeyValue = <U extends keyof T, T extends object>(key: U) => (obj: T) =>
  obj[key];

interface User {
  name: string;
  age: number;
}

const user: User = {
  name: "John Smith",
  age: 20
};

const getUserName = getKeyValue<keyof User, User>("name")(user);

// => 'John Smith'

वैकल्पिक वाक्य रचना

const getKeyValue = <T, K extends keyof T>(obj: T, key: K): T[K] => obj[key];

यदि यूजर के पास टाइप की तरह इंटरफेस है तो यह कैसे काम करेगा? मुझे एक त्रुटि मिलती है कि उन्हें 'स्ट्रिंग' को नहीं सौंपा जा सकता है।
— लॉकनीकेन


@AlexMckay तुम एक प्रतिभाशाली हो! उत्तर के लिए धन्यवाद,
— अविनाश

मैंने इस फ़ंक्शन के साथ एक छोटा सा npm पैकेज लिखा है , जो टाइपस्क्रिप्ट के लिए नए हैं। यह 38 बाइट्स एक बार में छोटा होता है और इसमें एक jsdoc टिप्पणी होती है ताकि यदि आप फ़ंक्शन पर हॉवर करते हैं तो यह ऊपर दिए गए उत्तर प्रदान करता है।
— एलेक्स मक्के

9

मैंने अपने getClassफंक्शन में इसी तरह के मुद्दे को हल किया :

import { ApiGateway } from './api-gateway.class';
import { AppSync } from './app-sync.class';
import { Cognito } from './cognito.class';

export type stackInstances = typeof ApiGateway | typeof  AppSync | typeof Cognito

export const classes = {
  ApiGateway,
  AppSync,
  Cognito
} as {
  [key: string]: stackInstances
};

export function getClass(name: string) {
  return classes[name];
}

मेरे लिखने से classesमेरी संघ प्रकार के साथ स्थिरांक टाइपप्रति खुश कर दिया और यह मेरे लिए समझ में आता है।


8

आपके पास सरल और मुहावरेदार टाइपस्क्रिप्ट के साथ दो विकल्प हैं:

  1. सूचकांक प्रकार का उपयोग करें
DNATranscriber: { [char: string]: string } = {
  G: "C",
  C: "G",
  T: "A",
  A: "U",
};

यह सूचकांक हस्ताक्षर है त्रुटि संदेश के बारे में बात कर रहा है। संदर्भ

  1. प्रत्येक संपत्ति टाइप करें:
DNATranscriber: { G: string; C: string; T: string; A: string } = {
  G: "C",
  C: "G",
  T: "A",
  A: "U",
};

पहला विकल्प एक इंटरफ़ेस को परिभाषित करने से आसान है। मुझे यह पसंद है
— drlingyi

1

मैं थोड़ी देर के लिए इसके साथ खिलवाड़ किया। यहाँ मेरा परिदृश्य था:

मेरे पास दो प्रकार हैं, मेट्रिक्स 1 और मेट्रिक्स 2, प्रत्येक में अलग-अलग गुण हैं:

type metrics1 = {
    a: number;
    b: number;
    c: number;
}

type metrics2 = {
    d: number;
    e: number;
    f: number;
}

मेरे कोड में एक बिंदु पर, मैंने एक ऑब्जेक्ट बनाया जो इन दो प्रकारों का प्रतिच्छेदन है क्योंकि यह ऑब्जेक्ट उनके सभी गुणों को रखेगा:

const myMetrics: metrics1 & metrics2 = {
    a: 10,
    b: 20,
    c: 30,
    d: 40,
    e: 50,
    f: 60
};

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

const myKey = 'a';
console.log(myMetrics[myKey]); // No issues, TypeScript has validated it exists

यदि, हालांकि, मैं एक गतिशील चर (जैसे चलो ) का उपयोग कर रहा हूं , तो टाइपस्क्रिप्ट यह जांचने में सक्षम नहीं होगा कि क्या संपत्ति संकलन समय के दौरान मौजूद है, और रनटाइम के दौरान अतिरिक्त मदद की आवश्यकता होगी। यह वह जगह है जहाँ निम्न प्रकार का गार्ड आता है:

function isValidMetric(prop: string, obj: metrics1 & metrics2): prop is keyof (metrics1 & metrics2) {
    return prop in obj;
}

यह के रूप में लिखा है, "यदि obj है संपत्ति प्रोप तो टाइपप्रति जानते हैं कि चलो प्रोप metrics1 और metrics2 के चौराहे में मौजूद है।" नोट : सुनिश्चित करें कि आप ऊपर दिखाए गए अनुसार keyof के बाद कोष्ठक में मेट्रिक्स 1 और मेट्रिक्स 2 को घेर लेते हैं , या फिर आप मेट्रिक्स 1 की कुंजी और मैट्रिक्स 2 (इसकी कुंजी नहीं) के बीच एक चौराहे के साथ समाप्त हो जाएंगे।

अब, मैं टाइपगार्ड का उपयोग कर सकता हूं और रनटाइम के दौरान सुरक्षित रूप से अपनी वस्तु तक पहुंच सकता हूं:

let myKey:string = '';
myKey = 'a';
if (isValidMetric(myKey, myMetrics)) {
    console.log(myMetrics[myKey]);
}

1

Google के लिए:

प्रकार 'स्ट्रिंग' के एक पैरामीटर के साथ कोई सूचकांक हस्ताक्षर टाइप पर नहीं मिला ...

सबसे अधिक संभावना है कि आपकी त्रुटि को पढ़ना चाहिए:

क्या आप keyof Number इसके बजाय एक और अधिक विशिष्ट प्रकार का उपयोग करने का मतलब है string?

मैंने इस तरह के कोड के साथ एक समान टाइपिंग इश्यू हल किया:

const stringBasedKey = `SomeCustomString${someVar}` as keyof typeof YourTypeHere;

इस समस्या ने मुझे त्रुटि का वास्तविक अर्थ जानने में मदद की।


1

ऐसा करके समस्या को हल किया:

export interface IItem extends Record<string, any> {
    itemId: string;
    price: number;
}

const item: IItem = { itemId: 'someId', price: 200 };
const fieldId = 'someid';

// gives you no errors and proper typing
item[fieldId]

क्या आप एक स्पष्टीकरण जोड़ सकते हैं कि कोड का यह ब्लॉक क्या करता है?
— रस्तलाम

0

ऐसे ही मामलों से जूझ रहे किसी के लिए भी

No index signature with a parameter of type 'string' was found on type X

साधारण वस्तुओं के साथ इसका उपयोग करने की कोशिश कर रहा है ( जैसे dicts के रूप में प्रयुक्त ):

DNATranscriber = {
   G:"C",
   C: "G",
   T: "A",
   A: "U"
}

और गणना की गई कुंजी से मूल्य को गतिशील रूप से एक्सेस करने की कोशिश कर रहा है:

const key = getFirstType(dnaChain);
const result = DNATranscriber[key];

और आपने ऊपर दिखाए गए अनुसार त्रुटि का सामना किया, आप कीऑफ़ ऑपरेटर का उपयोग कर सकते हैं और कुछ ऐसा प्रयास कर सकते हैं

const key = getFirstType(dnaChain) as keyof typeof DNATranscriber;

निश्चित रूप से आपको एक गार्ड की आवश्यकता होगी, resultलेकिन अगर यह कुछ कस्टम प्रकार के जादू से अधिक सहज लगता है, तो यह ठीक है।



0

यहाँ फ़ंक्शन उदाहरण ट्रिम जेनेरिक प्रकार ट्रिम ऑब्जेक्ट है

const trimArrayObject = <T>(items: T[]) => {

  items.forEach(function (o) {

    for (let [key, value] of Object.entries(o)) {

      const keyName = <keyof typeof o>key;

      if (Array.isArray(value)) {

        trimArrayObject(value);

      } else if (typeof o[keyName] === "string") {

        o[keyName] = value.trim();

      }

    }

  });

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