typescript

typescript 2.6 2



¿Cómo evito el error “La firma de índice del tipo de objeto tiene implícitamente un tipo ''cualquiera''” cuando se compila el mecanografiado con el indicador noImplicitAny habilitado? (12)

¿Sin indexador? ¡Entonces haz el tuyo!

Globalmente he definido esto como una manera fácil de definir una firma de objeto. T puede ser any si es necesario:

type Indexer<T> = { [ key: string ]: T };

Solo agrego indexer como miembro de la clase.

indexer = this as unknown as Indexer<Fruit>;

Así que termino con esto:

constructor(private breakpointResponsiveService: FeatureBoxBreakpointResponsiveService) { } apple: Fruit<string>; pear: Fruit<string>; // just a reference to ''this'' at runtime indexer = this as unknown as Indexer<Fruit>; something() { this.indexer[''apple''] = ... // typed as Fruit

La ventaja de hacer esto es que recupera el tipo correcto: muchas soluciones que usan <any> perderán el tipeo por usted. Recuerde que esto no realiza ninguna verificación de tiempo de ejecución. Aún deberá comprobar si existe algo si no sabe con certeza si existe.

Si desea ser demasiado cauteloso, y está usando strict , puede hacer esto para revelar todos los lugares que puede necesitar para hacer una verificación explícita indefinida:

type OptionalIndexed<T> = { [ key: string ]: T | undefined };

Por lo general, no encuentro esto necesario ya que si tengo como propiedad de cadena de algún lugar, generalmente sé que es válido.

Este método me ha resultado especialmente útil si tengo mucho código que necesita acceder al indexador, y la escritura se puede cambiar en un solo lugar.

Nota: Estoy usando el modo strict , y lo unknown es definitivamente necesario.

El código compilado solo será indexer = this , por lo que es muy similar a cuando _this = this crea _this = this para usted.

Siempre compilo Typecript con la bandera --noImplicitAny. Esto tiene sentido ya que quiero que mi verificación de tipo sea lo más ajustada posible.

Mi problema es que con el siguiente código obtengo el error La Index signature of object type implicitly has an ''any'' type :

interface ISomeObject { firstKey: string; secondKey: string; thirdKey: string; } let someObject: ISomeObject = { firstKey: ''firstValue'', secondKey: ''secondValue'', thirdKey: ''thirdValue'' }; let key: string = ''secondKey''; let secondValue: string = someObject[key];

Es importante tener en cuenta que la idea es que la variable clave proviene de otro lugar de la aplicación y puede ser cualquiera de las claves del objeto.

He intentado explícitamente el tipo por:

let secondValue: string = <string>someObject[key];

¿O mi escenario simplemente no es posible con --noImplicitAny ?


Crear una interfaz para definir la interfaz ''indexador''

Luego crea tu objeto con ese índice.

Nota: esto seguirá teniendo los mismos problemas que otras respuestas han descrito con respecto a la aplicación del tipo de cada elemento, pero a menudo eso es exactamente lo que desea.

Puede hacer que el parámetro de tipo genérico sea lo que necesite: ObjectIndexer< Dog | Cat> ObjectIndexer< Dog | Cat>

// this should be global somewhere, or you may already be // using a library that provides such a type export interface ObjectIndexer<T> { [id: string]: T; } interface ISomeObject extends ObjectIndexer<string> { firstKey: string; secondKey: string; thirdKey: string; } let someObject: ISomeObject = { firstKey: ''firstValue'', secondKey: ''secondValue'', thirdKey: ''thirdValue'' }; let key: string = ''secondKey''; let secondValue: string = someObject[key];

Zona de juegos mecanografiada

Incluso puede usar esto en una restricción genérica al definir un tipo genérico:

export class SmartFormGroup<T extends IndexableObject<any>> extends FormGroup

Entonces T dentro de la clase se puede indexar :-)


Agregar una firma de índice le permitirá a TypeScript saber cuál debería ser el tipo.

En su caso, sería [key: string]: string;

interface ISomeObject { firstKey: string; secondKey: string; thirdKey: string; [key: string]: string; }

Sin embargo, esto también exige que todos los tipos de propiedad coincidan con la firma del índice. Como todas las propiedades son una string , funciona.

Si bien las firmas de índice son una forma poderosa de describir la matriz y el patrón de ''diccionario'', también imponen que todas las propiedades coincidan con su tipo de retorno.

Editar:

Si los tipos no coinciden, se puede usar un tipo de unión [key: string]: string|IOtherObject;

Con los tipos de unión, es mejor si deja que TypeScript infiera el tipo en lugar de definirlo.

// Type of `secondValue` is `string|IOtherObject` let secondValue = someObject[key]; // Type of `foo` is `string` let foo = secondValue + '''';

Aunque eso puede ser un poco complicado si tiene muchos tipos diferentes en las firmas de índice. La alternativa a eso es usar any en la firma. [key: string]: any; Entonces necesitarías lanzar los tipos como hiciste anteriormente.


Declara el objeto así.

export interface Thread { id:number; messageIds: number[]; participants: { [key:number]: number }; }


En la actualidad, la mejor solución es declarar tipos. Me gusta

enum SomeObjectKeys { firstKey = ''firstKey'', secondKey = ''secondKey'', thirdKey = ''thirdKey'', } let someObject: Record<SomeObjectKeys, string> = { firstKey: ''firstValue'', secondKey: ''secondValue'', thirdKey: ''thirdValue'', }; let key: SomeObjectKeys = ''secondKey''; let secondValue: string = someObject[key];


La siguiente configuración de tsconfig le permitirá ignorar estos errores: configúrelo como verdadero.

suppressImplicitAnyIndexErrors

Suprima noImplicitAny errores para indexar objetos que carecen de firmas de índice.


La solución ''keyof'' mencionada anteriormente funciona. Pero si la variable se usa solo una vez, por ejemplo, recorrer un objeto, etc., también puede escribirla.

for (const key in someObject) { sampleObject[key] = someObject[key as keyof ISomeObject]; }


La solución más simple que pude encontrar usando el Script 3.1 en 3 pasos es:

1) Hacer interfaz

interface IOriginal { original: { [key: string]: any } }

2) Hacer una copia mecanografiada

let copy: IOriginal = (original as any)[key];

3) Usar en cualquier lugar (JSX incluido)

<input customProp={copy} />


Otra forma de evitar el error es usar el elenco de esta manera:

let secondValue: string = (<any>someObject)[key]; (Tenga en cuenta el paréntesis)

El único problema es que esto ya no es de tipo seguro, ya que está enviando a any . Pero siempre puedes volver al tipo correcto.

ps: estoy usando el mecanografiado 1.7, no estoy seguro de las versiones anteriores.


Similar a la respuesta de @Piotr Lewandowski, pero dentro de forEach :

const config: MyConfig = { ... }; Object.keys(config) .forEach((key: keyof MyConfig) => { if (config[key]) { // ... } });


use keyof typeof

const cat = { name: ''tuntun'' } const key: string = ''name'' cat[key as keyof typeof cat]


TypeScript 2.1 introdujo una forma elegante de manejar este problema.

const key: (keyof ISomeObject) = ''secondKey''; const secondValue: string = someObject[key];

Podemos acceder a todos los nombres de propiedades del objeto durante la fase de compilación mediante la clave de la palabra clave (ver el changelog ).

Solo necesita reemplazar el tipo de variable de string con keyof ISomeObject . Ahora el compilador sabe que la variable key solo puede contener nombres de propiedades de ISomeObject .

Ejemplo completo:

interface ISomeObject { firstKey: string; secondKey: string; thirdKey: number; } const someObject: ISomeObject = { firstKey: ''firstValue'', secondKey: ''secondValue'', thirdKey: 3 }; const key: (keyof ISomeObject) = ''secondKey''; const secondValue: string = someObject[key]; // You can mix types in interface, keyof will know which types you refer to. const keyNumber: (keyof ISomeObject) = ''thirdKey''; const numberValue: number = someObject[keyNumber];

Código en vivo en typescriptlang.org (establezca la opción noImplicitAny )

Lectura adicional con más keyof usos .