Определение типа в литерале объекта в TypeScript
В TypeScript в классе можно объявить тип для свойства, например:
class className{
property : string;
};
Как я должен написать код, чтобы объявить тип для свойства в литерал объекта? Такой код не компилируется:
var obj = {
property: string;
};
(Я получаю сообщение об ошибке - имя "строка" не существует в текущей области).
Что я делаю не так или это баг?
15 ответов
Вы довольно близко, вам просто нужно заменить =
с :
, Вы можете использовать литерал типа объекта (см. Раздел 3.5.3 спецификации) или интерфейс. Использование литерала типа объекта близко к тому, что у вас есть:
var obj: { property: string; } = { property: "foo" };
Но вы также можете использовать интерфейс
interface MyObjLayout {
property: string;
}
var obj: MyObjLayout = { property: "foo" };
Используйте оператор приведения, чтобы сделать это кратким (приведя значение null к нужному типу).
var obj = {
property: <string> null
};
Более длинный пример:
var call = {
hasStarted: <boolean> null,
hasFinished: <boolean> null,
id: <number> null,
};
Это гораздо лучше, чем две части (одна для объявления типов, вторая для объявления значений по умолчанию):
var callVerbose: {
hasStarted: boolean;
hasFinished: boolean;
id: number;
} = {
hasStarted: null,
hasFinished: null,
id: null,
};
Обновление 2016-02-10 - для обработки TSX (спасибо @ Джош)
Используйте оператор as для TSX.
var obj = {
property: null as string
};
Более длинный пример:
var call = {
hasStarted: null as boolean,
hasFinished: null as boolean,
id: null as number,
};
Я удивлен, что никто не упомянул об этом, но вы могли бы просто создать один интерфейс под названием ObjectLiteral
, как это:
interface ObjectLiteral {
[key: string]: any;
}
Тогда вы бы использовали его, вот так:
let data: ObjectLiteral = {
hello: "world",
goodbye: 1,
// ...
};
Вы можете повторно использовать этот единственный интерфейс много раз, как захотите.
Удачи.
Если ваши свойства имеют один и тот же тип, вы можете использовать предопределенный тип утилиты Record
:
type Keys = "property" | "property2"
const obj: Record<Keys, string> = {
property: "my first prop",
property2: "my second prop",
};
Конечно, вы можете пойти дальше и определить собственный тип для значений свойств:
type Keys = "property" | "property2"
type Values = "my prop" | "my other allowed prop"
const obj: Record<Keys, Values> = {
property: "my prop",
property2: "my second prop", // TS Error: Type '"my second prop"' is not assignable to type 'Values'.
};
Если вы пытаетесь написать аннотацию типа, синтаксис:
var x: { property: string; } = ...;
Если вы пытаетесь написать литерал объекта, синтаксис:
var x = { property: 'hello' };
Ваш код пытается использовать имя типа в позиции значения.
Если вы пытаетесь добавить типизацию к литералу деструктурированного объекта, например, в аргументах функции, синтаксис:
function foo({ bar, baz }: { bar: boolean, baz: string }) {
// ...
}
foo({ bar: true, baz: 'lorem ipsum' });
В машинописи, если мы объявляем объект, то
[модификатор доступа] имя переменной: { // структура объекта}
private Object:{Key1:string , Key2:number }
Остерегаться. Некоторым это может показаться очевидным, но объявление типа
const foo:TypeName = {}
это не то же самое по сравнению с литьем с
as
const foo = {} as TypeName
несмотря на предложения использовать другие ответы.
Пример:
const foo: { [K in 'open' | 'closed']: string } = {}
// ERROR: TS2739: Type '{}' is missing the following properties from type '{ open: string; closed: string; }': open, closed
Спасибо, безопасность типов!
const foo = {} as { [K in 'open' | 'closed']: string }
// No error
Прощай, безопасность типов!
Вот что я делаю в 2021 году:
const sm = {
currentCacheName: '' as string,
badSWTimer: 0 as number,
reg: {} as ServiceWorkerRegistration,
quantum: null as number | null
}
Это не просто приведение значения, оно работает так же, как определение интерфейса для свойств объекта.
// Use ..
const Per = {
name: 'HAMZA',
age: 20,
coords: {
tele: '09',
lan: '190'
},
setAge(age: Number): void {
this.age = age;
},
getAge(): Number {
return age;
}
};
const { age, name }: { age: Number; name: String } = Per;
const {
coords: { tele, lan }
}: { coords: { tele: String; lan: String } } = Per;
console.log(Per.getAge());
Начиная с TypeScript 4.9, оператор satisfies можно использовать для создания встроенных утверждений. Вы можете использовать его для одного значения или всего объекта следующим образом:
interface NameInfo {
first: string;
last: string | undefined;
}
const people = {
john: { first: "John", last: "Doe" },
jane: { first: "Jane", last: "Doe" } satisfies NameInfo,
} satisfies Record<string, NameInfo>;
Другой вариант — создать класс со статическими свойствами:
class TestData {
static people: Record<string, NameInfo> = {
john: { first: "John", last: "Doe" },
jane: { first: "Jane", last: "Doe" },
};
}
В вашем коде:
var obj = {
myProp: string;
};
Фактически вы создаете литерал объекта и назначаете переменную строку свойству myProp. Хотя это очень плохая практика, на самом деле это будет действительный код TS (не используйте его!):
var string = 'A string';
var obj = {
property: string
};
Однако вы хотите, чтобы литерал объекта был типизирован. Этого можно добиться разными способами:
Интерфейс:
interface myObj {
property: string;
}
var obj: myObj = { property: "My string" };
Пользовательский тип:
type myObjType = {
property: string
};
var obj: myObjType = { property: "My string" };
Оператор приведения:
var obj = {
myString: <string> 'hi',
myNumber: <number> 132,
};
Литерал типа объекта:
var obj: { property: string; } = { property: "Mystring" };
- создать тип с помощью ключевого слова типа
type ObjType = {
property: string;
}
а затем вы можете использовать его для привязки вашего объекта, чтобы он принимал только этот тип, как показано ниже.
const obj: ObjType = {
property: "TypeScript"
}
Просто чтобы расширить ответ @RickLove...
Это прекрасно работает, так как вам нужно только определить тип, который не может быть выведен:
const initialState = {
user: undefined as User | undefined,
userLoading: false
};
и он преобразуется в этот код js:
const initialState = {
user: undefined,
userLoading: false
};
И если вам нужно извлечь его в тип, вы можете просто сделать это:
export type InitState = typeof initialState;
Преобразование литерала объекта в тип с помощью DRY
Просто делать:
const myObject = {
hello: 'how are you',
hey: 'i am fine thank you'
}
type myObjectType = keyof typeof MyObject
Работа сделана!