Garret Harp
10/22/2021, 5:45 PMimport { Record, String } from 'runtypes'
const DynamoItem = Record({
id: String,
something: String,
else: String
})
export const getItem = async (id: string, attributes?: Parameters<typeof DynamoItem.pick>) => {
const { Item } = await dynamo.get({ id }, { attributes })
if (!Item) throw new Error('No item')
return attributes ? DynamoItem.pick(attributes).check(Item) : DynamoItem.check(Item)
}
Currently its always the full "DynamoItem" type even when I call getItem('myItemId', 'id')
Ashishkumar Pandey
10/22/2021, 5:49 PMconst DynamoItem = Record({
id: String,
something: String.optional(),
else: String.optional()
})
This should help.Ashishkumar Pandey
10/22/2021, 5:50 PMGarret Harp
10/22/2021, 5:52 PMGarret Harp
10/22/2021, 5:55 PMgetItem('myItemId')
shows the type to be the full "DynamoItem" which is what I want.
Was hoping to be able to pass in an array of attributes I want to retrieve from dynamo and my return type reflect that I only have a subset of the attributes.
Calling getItem('myItemId', ['id'])
should show as type { id: string }
getItem('myItemId', ['id', 'something'])
should show as type { id: string; something: string }
etcAshishkumar Pandey
10/22/2021, 5:55 PMthdxr
10/22/2021, 5:57 PMthdxr
10/22/2021, 5:57 PMthdxr
10/22/2021, 5:57 PMthdxr
10/22/2021, 5:59 PMzod
this should work
function getItem<T extends Parameters<typeof DynamoItem.pick>>(id: string, attributes: T) {
const { Item } = await dynamo.get({ id }, { attributes })
if (!Item) throw new Error('No item')
return attributes ? DynamoItem.pick(attributes).check(Item) : DynamoItem.check(Item)
}
Garret Harp
10/22/2021, 6:08 PMthdxr
10/22/2021, 6:10 PMthdxr
10/22/2021, 6:10 PMas T
when returning and that should workGarret Harp
10/22/2021, 6:11 PMthdxr
10/22/2021, 6:11 PMGarret Harp
10/22/2021, 6:11 PMthdxr
10/22/2021, 6:13 PMGarret Harp
10/22/2021, 6:14 PMthdxr
10/22/2021, 7:02 PMthdxr
10/22/2021, 7:02 PMconst Thing = Record({
a: String,
b: String,
c: String,
});
type ThingPickable = Parameters<typeof Thing.pick>;
function narrow<T extends ThingPickable>(...attributes: T) {
const item: unknown = {};
return Thing.pick<T[number]>(...(attributes as any)).check(item);
}
const narrowed = narrow("a", "b");
thdxr
10/22/2021, 7:02 PMthdxr
10/22/2021, 7:11 PMtype ThingPickable = Parameters<typeof Thing.pick>;
function narrow<T extends ThingPickable>(...attributes: T) {
const item: unknown = {};
const result = Thing.pick(...(attributes as any)).check(
item
);
return result as Pick<Static<typeof Thing>, T[number]>
}
const narrowed = narrow("a", "b");
thdxr
10/22/2021, 7:11 PMGarret Harp
10/22/2021, 7:16 PMÖmer Toraman
10/22/2021, 11:59 PMÖmer Toraman
10/23/2021, 12:01 AMÖmer Toraman
10/23/2021, 12:01 AMGarret Harp
10/23/2021, 12:05 AMÖmer Toraman
10/23/2021, 12:07 AMÖmer Toraman
10/23/2021, 12:08 AMÖmer Toraman
10/23/2021, 12:08 AMGarret Harp
10/23/2021, 12:10 AMÖmer Toraman
10/23/2021, 12:16 AMGarret Harp
10/31/2021, 3:29 AMimport * as Rt from 'runtypes'
const UserItem = Rt.Record({
name: Rt.String,
email: Rt.String,
id: Rt.String
})
type Model = {
get: (id: unknown, opts: unknown) => Promise<unknown>
}
const UserModel: Model = {
get: async (id: unknown) => ({ id, name: 'test', email: '<mailto:test@test.com|test@test.com>' })
}
const createFilteredGet = <T extends Rt.Record<{ [key: string]: Rt.Runtype }, false>>(runtype: T, model: Model) => {
return async <A extends Parameters<typeof runtype.pick>>(id: unknown, attributes?: A) => {
const item = await model.get(id, { attributes })
if (!item) return null
return attributes ? runtype.pick<A[number]>(...attributes as any).check(item) : runtype.check(item)
}
}
const getUser = createFilteredGet(UserItem, UserModel)
getUser('1', ['id']).then(item => {
// item should be typed as { id: string } | null but currently { [key: string]: unknown } | null
console.log(item)
})