-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Amplify JS TypeScript Improvements #11113
Comments
Awesome improvements here! My specific feedback is for the
|
Awesome! I'm excited about having types for the auth channel's event payload, after realizing a while ago that the payload of a "signIn" event differs depending on whether it originates from native Cognito or a social provider sign in. |
I wonder, though, what the flattened to the lowest level response would look like for an error case. Right now, there's a data object and an array of errors in the response in an error case. While I agree that Option 1 is more straight-forward for the happy case, I believe Option 2 would make error handling easier for a single query/mutation. |
Looking great so far! Halfway through, but I have a question about the Custom Event Data types in the proposed experience. Are those custom types made manually or are they coming from Codegen somehow? |
Yes, this answers my question. Thank you! |
This is more a question than anything, but it sits sort of in the same vein as this: Are there any plans on including some way to get credentials directly through the refresh token? Using the Auth code manually in a react app (for some reason) still kept the user credentials. In trying to set up an Angular app I've run into the only place that has a way that I can see to refresh the session is on the CognitoUser (which honestly I would like to see some improvements to as well, but that's a separate topic). It feels like there should be, and it is entirely possible I'm missing it since the docs for the library could be improved, but if we are going to talk about improving the types of the repo, this feels like something that should be added to it as well. |
Are errors thrown by the Auth package considered? I use them. |
@ebisbe That's correct, we'll be improving our type support for Auth errors emitted by the library. @jhechtf Thank you for your feedback! It is currently possible to refresh the session via currentSession if that resolves your issue. If you're still having trouble I'd recommend opening a ticket for us to debug further. |
Not all types are importable. For example I need |
Seconding @therealkh, even if you can't think of a reason why someone downstream would need access to a type, please export it wherever possible. |
It would be helpful to have an easy to use type serving as the parent of a model: Current Usage async fetchModelByID(model: any, id: string): Promise<any> {
try {
return await DataStore.query(model, (m) => m.id.eq(id)); <-- Warns that m is of type any
} catch (error) {
...
}
} Proposed Usage async fetchModelByID(model: ModelClass, id: string): Promise<ModelClass> {
try {
return await DataStore.query(model, (m) => m.id.eq(id)); <-- Would detect m being of type ModelClass
} catch (error) {
...
}
} For example, assume I have a user model, I could call: const user = fetchModelByID(User, id) |
Hey @jimblanc its great to see the TS improvements! I have some questions: Will the provided example in JS also be available as TS example? Currently it is not possible (without some janky hacking) to rewrite the example as same example in Typescript due to this issue: #7426 & #9968 and thats not great at all. Hope withSSRContext will get type definitions too. Especially the SSR part of the example.
Is there any ETA for all the TS improvements? |
Hi @BearCooder - all of our examples will have TS variations! On the hacky workarounds for enabling TypeScript, we are fully aware of those, and we will be resolving them in our next major version of the Amplify JavaScript library. We do not have an ETA at this time, but we will keep this RFC updated as we move forward! |
Something I came across today. Based on the current docs, I believe that the correct way of currently using amplify is // GOOD
import { Storage } from 'aws-amplify';
// BAD
import { Storage } from '@aws-amplify/storage' This makes sense to me because it ensures that all the different sub-packages get kept in sync. However, import { Auth, Hub } from 'aws-amplify';
import { CognitoHostedUIIdentityProvider, CognitoUser } from '@aws-amplify/auth'; This also means I either need to tell eslint not to complain about the second line or add So it would be good to have the useful types exported by aws-amplify. |
Hi @johnf - thank you for raising that concern! We are working with our team to make sure that these types are available to you even when using the |
Hey there, amazing AWS Amplify Team! First of all, I want to express my gratitude for creating such an awesome framework like AWS Amplify. You all rock! 🎉 I've been enjoying using Amplify for my various projects, but I noticed a couple of areas where we can make it even better, especially for TypeScript users like me. So, I'd like to request the following enhancements that would bring joy and smiles to developers worldwide:
// Spanish translation of the error message
case "Password must have uppercase characters":
SwalCustom(
"¡Error!",
"La contraseña debe contener al menos una letra mayúscula",
"error"
);
break; It would be super cool if Amplify could offer a built-in mechanism for error message translation. This way, we can provide smoother internationalization support without resorting to manual translations.
I believe implementing these enhancements would make AWS Amplify even more fantastic, and developers like me would be over the moon! Thank you for considering my suggestions, and keep up the great work! 🚀 Cheers, |
Hi @IamCocoDev - thank you for the positivity and encouragement - we appreciate that a lot! Regarding your mentioned points:
|
Hi AWS Amplify Team,
As for the topic of internationalization, I'd be happy to provide more details and a feature request on GitHub. Here's a brief overview of what I envision: Error Message Translation: It would be wonderful if AWS Amplify could offer a built-in mechanism for error message translation. Ideally, this feature would allow developers to:
This way, developers wouldn't need to hardcode translations manually, making it much easier to support international users. I believe this addition would be a game-changer for applications targeting a global audience. Once again, thank you for considering these suggestions and for your dedication to making AWS Amplify even better. Your responsiveness and commitment to the developer community are truly commendable! Looking forward to the continued evolution of AWS Amplify. Best regards, |
(Another request for TS improvement - not sure if this is best place to post? - admin please move if not) A few people have asked for type improvement for the Lambda function resolver, ie Structure of the function event; I have solved it in my own code: Solutionimport {
type AppSyncIdentity,
type AppSyncResolverEventHeaders,
} from 'aws-lambda'
/**
* See https://docs.amplify.aws/cli/graphql/custom-business-logic/#lambda-function-resolver
*
* @param TArguments type of the arguments
* @param TSource type of the source
*/
export interface AmplifyResolverEvent<
TArguments,
TSource = Record<string, any> | null,
> {
/**
* typeName: The name of the parent object type of the field being resolved.
*/
typeName: string
/**
* fieldName: The name of the field being resolved.
*/
fieldName: string
/**
* arguments: A map containing the arguments passed to the field being resolved.
*/
arguments: TArguments
/**
* identity: A map containing identity information for the request. Contains a nested key 'claims' that will contains the JWT claims if they exist.
*/
identity?: AppSyncIdentity
/**
* source: When resolving a nested field in a query, the source contains parent value at runtime. For example when resolving Post.comments, the source will be the Post object.
*/
source: TSource
/**
* request: The AppSync request object. Contains header information.
*/
request: {
headers: AppSyncResolverEventHeaders
/** The API's custom domain if used for the request. */
domainName: string | null
}
/**
* prev: When using pipeline resolvers, this contains the object returned by the previous function. You can return the previous value for auditing use cases.
*/
prev: { result: Record<string, any> } | null
}
I gathered this by looking at interface AppSyncResolverEvent in aws-lambda which speciflly mentions And in the AppSync mapping template resolver we can see how this type is built:Before mapping template:
Request Mapping Template:
Happy to open a PR (not sure where this would live) or leave here, not sure on best workflow. |
Hi @samturner3 - we're tracking the backend part of "typescript" support. Your concerns are very valid and we'd love to share some of our thinking with you. LMK if you're interested to hop on a call to get a sneak peak. If so, email me at: renbran at amazon dot com |
With the release of the latest major version of Amplify (aws-amplify@>6), we'll close this RFC. Please refer to our release announcement, migration guide, and documentation for more information. |
RFC: Amplify JS TypeScript Improvements
This issue is a Request For Comments (RFC). It is intended to elicit community feedback regarding a proposed change to the library. Please feel free to post comments or questions here.
Amplify JS is looking to improve our TypeScript support across the library to better serve our customers and provide a more intuitive & idiomatic developer experience. To this end, we are requesting your feedback on a variety of changes and improvements that will be available to you in our next major version release.
This RFC is broken down into sections covering:
Hub
and Amplify configurationAuth
,Storage
, andAPI
categories and associated APIsWe're also requesting feedback on any other TypeScript issues or pain points that you may have encountered not explicitly covered in this RFC.
Library-wide TypeScript Improvements
Amplify JS will be making the following improvements to our TypeScript support. These improvements will be applied across the entire library, not just the categories highlighted below.
strict
typings — We will be applyingstrict
mode to the entire library to improve the usability of our types. This will allow you to more easily construct API requests, avoid errors, and have higher confidence when handling API responses. Amplify JS will just work with your application without any additional configurations if you have strict mode on.skipLibCheck
when using Amplify with newer versions of TypeScript.Related issues:
Utility Changes
Amplify is proposing the following changes to our core utilities.
TypeScript support for Amplify Hub channels
We are improving developer experience by adding strict type support to Hub channels, events, and payloads. An example of the developer experience when listening for
auth
events is highlighted below.Amplify Channel Usage
Current DX (v5)
Proposed DX (v6)
TypeScript support for custom Hub channels
We are improving developer experience by adding strict type support to custom Hub channels, events, and payloads.
Current Usage (v5)
Proposed Usage (v6)
Related issue: Fully typed hubs (#5997)
TypeScript support for Amplify Configuration
To help developers configure Amplify categories, we are introducing type support for the
Amplify.configure
API. This will allow you to easily setup your AWS resources if you are connecting Amplify JS to resources you have not created directly with the Amplify CLI. The examples below demonstrate anAuth
configuration.Current Usage (v5)
Proposed Usage (v6)
Related issue:
A suggestion regarding typings for the Amplify.configure() function (#5095)
Try out the proposed types here: https://stackblitz.com/edit/rfc-typescript-v6?file=examples-core.ts
Auth
Category ChangesAmplify is proposing the following changes for the
Auth
category. Similar changes will be applied across all of theAuth
APIs but examples for specific APIs are highlighted below.TypeScript support for user attributes
User attributes inference on the
signUp
API.Current Usage (v5)
Proposed Usage (v6)
Related issue: TypeScript definition not matching: Property 'attributes' does not exist on type 'CognitoUser' (#9941)
Predictable API responses
We are improving DX by providing descriptive API responses to help developers complete auth flows. An example for the
confirmSignUp
API is highlighted below.Current Usage (v5)
Proposed Usage (v6)
Related issues:
Try out the proposed types here: https://stackblitz.com/edit/rfc-typescript-v6?file=examples-auth.ts
Storage
Category ChangesAmplify is proposing the following changes for the
Storage
category.Introduction of object reference types
In order to permit better interoperability between
storage
APIs we will introduceStorageObjectReference
&StoragePrefixReference
types to represent items in cloud storage. An example for copying an object from one access level to another is highlighted below.Current Usage (v5)
Proposed Usage (v6)
Splitting up the
get
APITo better capture customer intent and simplify API types we will split up the
get
API intogetUrl
&download
. An example for generating a pre-signed URL & downloading a file from the results of alist
operation is highlighted below.Current Usage (v5)
Proposed Usage (v6)
Changes to the
put
return objectTo better capture customer intent the
put
API will be renamed toupload
. Additionallyupload
will enable resumability by default in order to simplify API usage and remove the need to provide callbacks for monitoring upload status in favor of a Promise.Current Usage (v5)
Proposed Usage (v6)
Try out the proposed
storage
types here: https://stackblitz.com/edit/rfc-typescript-v6?file=examples-storage.tsGraphQL
API
Category ChangesAmplify is proposing the following changes for the GraphQL
API
category to improve type safety and readability.Introduce dedicated, type-safe
query()
,mutation()
, andsubscription()
GraphQL operation APIsTo better capture customer intent and simplify API types we will introduce dedicated APIs for queries, mutations, and subscriptions. We're going to retain the
graphql()
operation in case you want to issue multiple queries/mutations in a single request.Current Usage (v5)
Proposed Usage (v6)
Less verbose type definitions for generated queries, mutations, and subscriptions
In v6, we want to reduce the verbosity of the typings for the code-generated queries, mutations, and subscriptions by inferring their types from the generated code.
Current Usage (v5)
Proposed Usage (v6)
Flatten GraphQL operation responses
As alluded to in the previous section, we're looking to flatten the results of GraphQL operations to make them more easily accessible instead of the current three-levels-deep nested object. Would love to get your understanding on which option you prefer.
Current Usage (v5)
Proposed behavior for single query/mutation in the response
Proposed Option 1: Flatten to the lowest level (v6)
Proposed Option 2: Flatten to the
data
level (v6)Proposed behavior for multiple queries/mutations in the response
In GraphQL, you can define multiple queries or mutations in a single request via the
.graphql()
operation. The response object will include the result of all the queries and mutations. For example, given the following queries:Proposed Option 1: Flatten to data level
Proposed Option 2: Flatten to the array level
Proposed Option 3: Don't flatten at all
Type safety for GraphQL query, mutation, subscription inputs
In v6, we want to ensure type safety on GraphQL inputs if you use one of the generated GraphQL queries, mutations, or subscriptions.
Current Usage (v5)
Proposed Usage (v6)
Bug fix: Add
__typename
to GraphQL operations' selection setCurrently there's a bug in which the generated API types contain
__typenames
but not in the selection set of the generated GraphQL operations. This causes runtime type checking errors when you rely on TypeScript to expect the "__typename" field to be present but it isn't. Prior to the v6 launch, we'll fix this bug to ensure the type definition matches the selection set/return value of the GraphQL operation during runtime.Bug fix: Remove
any
cast needed for subscriptionsIn v5, there's a type mismatch bug for GraphQL subscriptions that forces the developer to cast to
any
to subscribe or unsubscribe. We plan on fixing this for v6.Current Usage (v5)
Proposed Usage (v6)
REST
API
Category ChangesAmplify is proposing the following changes for the REST
API
category.First param is an object with named parameters
To improve the readability of our APIs we will be introducing an object parameter to capture request parameters.
Current Usage (v5)
Proposed Usage (v6)
Adding TypeScript generics to request body and response
To improve developer experience and permit more strict typing we will be adding generic support to our
API
category APIs.Current Usage (v5)
Amplify v5 does not support using generics for the request body or response.
Proposed Usage (v6)
Type narrowing on runtime errors
Current Usage (v5)
Amplify v5 does not support narrowing down errors.
Proposed Usage (v6)
Try out the proposed
api
types here: https://stackblitz.com/edit/rfc-typescript-v6?file=examples-api.tsThe text was updated successfully, but these errors were encountered: