Cách viết lại mã để tránh TSLint "truy cập đối tượng thông qua chuỗi ký tự"


81

Tôi khá mới với TypeScript và tôi muốn biết liệu có tồn tại một cách hay để viết lại mã để tránh lỗi TSLint "truy cập đối tượng qua chuỗi ký tự không được phép" trong đoạn mã sau đây không

interface ECType
{
    name: string;
    type: string;
    elementType?: string;
}

export var fields: { [structName: string]: Array<ECType>; } = { };

class ECStruct1 {
    foo: string;
    bar: number;
    baz: boolean;
    qux: number;
    quux: number;
    corge: ECStruct2[];
    grault: ECStruct2;

    constructor() {
        ...
    }
} 

fields['ECStruct1'] = [
    { name: 'foo', type: 'string' },
    { name: 'bar', type: 'int' },
    { name: 'baz', type: 'bool' },
    { name: 'qux', type: 'long' },
    { name: 'quux', type: 'ulong' },
    { name: 'corge', type: 'array', elementType: 'ECStruct2' },
    { name: 'grault', type: 'ECStruct2' }
];

Cập nhật : Ở phần cuối, nội dung ở trên sẽ là một phần của tệp tự tạo có hơn 300 ECStructgiây, vì vậy tôi muốn có định nghĩa lớp (ví dụ ECStruct1) theo sau là mô tả meta của nó (ví dụ fields['ECStruct1']).


4
Tôi chưa bao giờ sử dụng TS nhưng nhìn vào lỗi và xem mã, tôi muốn nói rằng bạn cần thay thế fields['ECStruct1']bằng fields.ECStruct1. Sử dụng ký hiệu dấu chấm để truy cập đạo cụ đối tượng thường được ưu tiên hơn truy cập theo chuỗi ký tự.
Jamie Dixon

1
Cảm ơn. Tôi đã thử nó rồi nhưng fields.ECStruct1=không được trình biên dịch TS cho phép: Lỗi TS2339 Thuộc tính 'ECStruct1' không tồn tại trên loại '{[structName: string]: ECType []; } '.
Denis Cappellin

Câu trả lời:


147

Bạn có một số tùy chọn ở đây:

Chỉ cần vô hiệu hóa quy tắc

/* tslint:disable:no-string-literal */
whatever.codeHere()
/* tslint:enable:no-string-literal */

Sử dụng một biến thay vì một chuỗi ký tự

// instead of 
fields['ECStruct1'] = ...
// do something like
let key = 'ECStruct1';
fields[key] = ...

Viết / Tạo giao diện rõ ràng

Xem câu trả lời của MartylX ở trên . Bản chất:

interface ECFieldList {
    ECStruct1: ECType[];
}

export var fields:ECFieldList = {
    ECStruct1: [
        ...

Bất kỳ giải pháp nào trong số này đều là các giải pháp hợp lý, mặc dù tôi không phải là fan hâm mộ của # 2 vì nó làm xáo trộn mã của bạn mà không có lý do chính đáng. Nếu bạn vẫn đang tạo mã, có lẽ việc tạo một loại fieldsnhư trong # 3 là một giải pháp tốt.


48

Bạn có thể thoát khỏi quy tắc. Hãy tìm tslint.json, thêm một thuộc tính "no-string-literal"với false, trong rules::

{
"rules": {
    "no-string-literal": false,
    ... other rules ...

39

Chỉ cần sử dụng chú thích theo nghĩa đen của mẫu.

fields[`ECStruct1`]

2
đẹp và đơn giản. Cảm ơn!
brando

4
Thủ đoạn xấu xí vì nó đánh bại mục đích của cảnh báo. nhưng nó giải quyết vấn đề của tôi theo một cách đơn giản.
LosManos

1
hack của một năm!
Kacpers

6

Còn cách này thì sao? Tôi không biết bạn có cần indexer ( [structName: string]: Array<ECType>;) hay không.

interface ECType {
    name: string;
    type: string;
    elementType?: string;
}

interface ECFieldList {
    ECStruct1: ECType[];
}

export var fields:ECFieldList = {
    ECStruct1: [
        {name: 'foo', type: 'string'},
        {name: 'bar', type: 'int'},
        {name: 'baz', type: 'bool'},
        {name: 'qux', type: 'long'},
        {name: 'quux', type: 'ulong'},
        {name: 'corge', type: 'array', elementType: 'ECStruct2'},
        {name: 'grault', type: 'ECStruct2'}
    ]
};

Tôi đã chỉnh sửa câu hỏi của mình và thêm nhiều chi tiết hơn, vì vậy nhận xét này phải rõ ràng. Tôi muốn tránh có interfacevới N định nghĩa về ECStructvà sau đó là export var fields...nơi tôi viết các định nghĩa thực sự của mỗi ECStruct.
Denis Cappellin

Cài đặt của bạn cho tslint là gì? Tôi đoán bạn đã kích hoạt no-string-literal(Không cho đối tượng truy cập thông qua xâu -. Npmjs.com/package/tslint )
Martin Vseticka

1
Có, bây giờ tôi đã no-string-literalbật tùy chọn trên toàn cầu và chỉ trong tệp có mã ở trên, tôi đã tắt tùy chọn đó bằng nhận xét /* tslint:disable: no-string-literal */.
Denis Cappellin

Tốt, hãy sử dụng cú pháp ngoặc với các biến (tức là fields[variable]) và cú pháp dấu chấm với chuỗi (tức là fields.ECStruct1) và bạn sẽ ổn.
Martin Vseticka

5

Có lẽ không phải là lựa chọn tốt nhất, nhưng sử dụng

fields['ECStruct1'.toString()]

cũng hoạt động


nhanh chóng và dễ dàng.
Dani

1
Vui lòng đừng làm vậy. Linter ở đó bởi vì người thiết lập dự án muốn bạn tuân theo các phương pháp mã tốt nhất, không vi phạm các quy tắc của linter.
Andy

0

Một cách đơn giản là xác định một biến để giữ giá trị của ECStruct1:

const sampleName = 'ECStruct1';

và sau đó, có quyền truy cập vào đối tượng bằng cách sử dụng biến làm chỉ mục:

fields[sampleName] ...
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.