2017-08-19 65 views
2

我用簡單的模式中的對象定義數據庫模式:打字稿動態創建界面

{ 
    name: 'string', 
    age: 'integer', 
    ... 
} 

是它在某種程度上可以創建該對象的接口或類,所以我不必鍵入一切兩次?

回答

4

你可以做到這一點,但除非你認爲你可能會改變模式,否則它可能比它的價值更麻煩。打字稿不具有內置的推斷中,你想辦法類型的方式,所以你必須同軸電纜和哄騙它這樣做:


首先,定義映射文字名稱的方式'string''integer'他們所代表的打字稿類型(分別大概stringnumber):

type MapSchemaTypes = { 
    string: string; 
    integer: number; 
    // others? 
} 
type MapSchema<T extends Record<string, keyof MapSchemaTypes>> = { 
    [K in keyof T]: MapSchemaTypes[T[K]] 
} 

現在,如果你可以像你所指定的一個適當類型的架構對象,並從它那裏得到相關類型:

const personSchema = {name: 'string', age: 'integer'}; 
type Person = MapSchema<typeof personSchema>; // ERROR 

糟糕,問題是personSchema被推斷爲{name: string; age: string}而不是所需的{name: 'string'; age: 'integer'}。你可以用類型註釋來解決這個問題:

const personSchema: { name: 'string', age: 'integer' } = { name: 'string', age: 'integer' }; 
type Person = MapSchema<typeof personSchema>; // {name: string; age: number}; 

但現在感覺就像你在重複自己。幸運的是,有一種方法可以強制它推斷出正確的類型:

function asSchema<T extends Record<string, keyof MapSchemaTypes>>(t: T): T { 
    return t; 
} 
const personSchema = asSchema({ name: 'string', age: 'integer' }); // right type now 
type Person = MapSchema<typeof personSchema>; // {name: string; age: number}; 

這很有效!


看到它在行動on the Typescript Playground。希望有所幫助;祝你好運!

0

我不認爲你可以聲明動態接口。但是,您可以爲具有已知屬性的對象創建一個type

您可以創建一個將字符串文字映射到實際類型的對象,例如, 'integer' => number,但這與問題無關。我不知道你在用什麼框架,但下面的例子適用於類似的框架:Mongoose。

users.js

export const UserSchema = mongoose.Schema({ 
    name: String, 
    value: Number 
}); 

export const Users = mongoose.Model('users', UserSchema); 

export type User = { [K in keyof typeof UserSchema]: any } ; 

用法:

import { User, Users } from './user'; 

Users.find({}).exec((err: Error, res: User) => { ... }) 

返回的結果應具有相同的密鑰爲UserSchema,但所有值映射到任何你仍然要映射字符串文字類型。