TypescriptBuild:Type '{ Id: number; title: string; Name: string; }[]' is not assignable to type - typescript1.4

enter image description hereI am trying to run below code in VS2017 typescript for Angular 2, getting an error. I have created CustomerViewModel also. I am unable to create an array list of class CustomerViewModel.
Here is the code,
enter image description here

Related

Gatsby createTypes don't create localFile using File

I have a problem to run Gatsby when there is a field in graphql that is empty (in cms sometimes the field will be empty sometimes not). I managed to solve this problem by adding in gatsby-node.js via createTypes the missing content. Unfortunately just as for the text using the string type works fine so for the photo using the File type subfield localFile is not created. I need the localFile to appear even if there is no photo, the same way as photo is added. Does anyone have an idea how to solve this. Thanks a lot in advance for your help.
gatsby-node.js
exports.sourceNodes = ({ actions }) => {
const { createTypes } = actions
const typeDefs = ` type StrapiPageEstimateRealizations implements Node {
Title: String
Description: String
Img: File
}
`
createTypes(typeDefs)
}
graphql when the photo field is empty
graphql when a picture is added in cms
File is not a native type so depending on the context, you need to add a custom type.
Try defining your custom type like:
type LocalFile {
localFile: File #link(from: "localFile___NODE")
}
And then:
const typeDefs = ` type StrapiPageEstimateRealizations implements Node {
Title: String
Description: String
Img: LocalFile
}
Useful resources:
https://github.com/gatsbyjs/gatsby/issues/29100

Using ClassNameMap or Record<string,string> type for passing styles from one component to another

I am trying to pass more than one class styles from one component to another.
From Component A I am doing this,
const useStyles = makeStyles(() =>
createStyles({
label:{
width: "100%",
height: "100%",
margin: "10px",
backgroundColor: "white",
},
flex:{
}
})
);
const styles=useStyles();
const getAllList=labelNames.map((name: string):ReactNode => {
return (<Load
label={name}
classes={styles.flex} //here showing error under classes as "Type 'string' is not assignable to type 'ClassNameMap<string> | undefined'."
width={"100%"}
onDataChange={(value: string, data: string): void => {
}}
/>);
});
In Load component I declared like below,
interface Props {
width: string;
label: string;
classes?: ClassNameMap;
onDataChange: (selectedvalue: string, data: string) => void;
}
"Type 'string' is not assignable to type 'ClassNameMap | undefined'."
above error I am getting in the line which I mentioned above. I am unable to find what need to do to fix the error. Any idea or suggestions will help me to resolve. Anyone have any idea about how to pass class styles to specific component.
Also, I need to pass more than one style as props.
ClassNameMap and Record<string, string> are essentially the same. Both are objects whose keys are strings and whose values are string class names. If you want to refine the keys to just the allowed class names, ClassNameMap<‘label’ | ‘flex’> is the same as Record<‘label’ | ‘flex’, string>.
That’s not your issue. Your problem is that the Load component expects an object of class names, but you are providing it with a single string class name styles.flex. That’s why you get the error message:
Type 'string' is not assignable to type 'ClassNameMap | undefined'.
Based on what you are saying here:
I need to pass more than one style as props
Probably you want to pass the entire object that you got from the useStyles hook. Pass classes={styles} instead of classes={styles.flex}.

graphql + mongoose + typescript, how to reduce model definition duplicated

I use mongoose, typescript and graphql to build my app.
I am a full-stack developer.
The problem is I define the fields and types of model FIVE times.
server side:
models/book.ts:
// first time
interface IBook extends mongoose.Document {
title: string;
author: string;
}
// second time
const bookSchema = new mongoose.Schema({
title: String,
author: String
})
const Book: mongoose.Model<IBook> = mongoose.model<IBook>('Book', bookSchema)
graphql/typeDefs.ts
const typeDefs = `
// third time
type Book {
title: String!
author: String!
}
// fourth time
input BookInput {
title: String!
author: String!
}
`
client side:
interfaces/book.ts
// fifth time
interface IBook {
title: string;
author: string;
}
As you can see. the title and author fields and types are defined FIVE times.
There are three main disadvantages:
duplicated
lack of maintainability
inefficient
Is there a way to solve this? I think this is almost a DRY problem.
Here are my thinkings:
universal app - extract some common modules used in client and server side.
make a tool handle this.
make a project generator or command line tool like ng-cli for generating model and types statically which means before the run-time
make model definition decorator or syntax sugar generate model and types dynamically at run-time
We recently ran into this issue, requiring us to maintaining a duplicated Typescript interface alongside our Mongoose schemas (for us the issue was solely server-side as we are not using graphql or client-side Typescript)
We built mongoose-tsgen to address this. It may not handle all cases concerned here, but could be easily bootstrapped to handle your use case.
It reads your Mongoose schemas and generates an index.d.ts file which includes an interface for each document and subdocument. These interfaces can be imported from the mongoose module directly like so:
import { IUser } from "mongoose"
async function getUser(uid: string): IUser {
// `user` is of type IUser
const user = await User.findById(uid)
return user;
}
In case anyone is still wondering,
You can use TypeGraphQL together with Typegoose to create all the schemas within one single class with decorators like this:
#ObjectType()
export class Book{
#Field() #prop({ required: true })
title!: string;
#Field() #prop({ required: true })
name!: string;
}

Is casting to "keyof T" suppose to work or result in a compile error?

Consider the following TypeScript example:
interface MyInterface{
Prop1: string;
Prop2: number;
Prop3: string;
}
const myVar = "Prop4" as keyof MyInterface;
Running this code in Visual Studio 2017, Visual Studio Code and in Playground successfully compiles (TypeScript 2.9.2); the string value is not type checked against MyInterface but both VS and VSC show the 3 properties of MyInterface as IntelliSense suggestions:
const myVar: keyof MyInterface = "Prop4"; obviously works as intended and throws an error but the first example neither throws an error, nor ensures type safety.
Is this statement legal? If so, how is it suppose to behave? If not, why does it compile?
You are using a type assertion, a type assertion by definition overrides what the compiler knows to be true with what you, as the developer decide is true. If you tell the compiler the string it knows not to be an key of MyInterface is a key of MyInterface it will accept this as it is designed to do (although it will prevent you from asserting between unrelated types, eg this will be an error: let d = true as keyof MyInterface;).
If you want a variable to be typed as the key of an interface but still check that the value assigned to it is valid you can specify the type explicitly as you have.
You could also use a helper function:
interface MyInterface {
Prop1: string;
Prop2: number;
Prop3: string;
}
function keyOf<T>(key: keyof T) {
return key;
}
const myVar = keyOf<MyInterface>("Prop4"); //Argument of type '"Prop4"' is not assignable to parameter of type '"Prop1" | "Prop2" | "Prop3"'.
const myVar2 = keyOf<MyInterface>("Prop3");
Playground link

ajax dependency selection plugin

Based on a previous post and some suggestions received there I have modified my application to use the ajax dependency selection plugin for some chained select lists that I have.
The select lists are Consultant -> Contract -> Project
I have a create page and edit page for an evaluation that use the same form template. On the create page my chained selects are working correctly and saving to the database. However when I open up an existing evaluation only the select primary select box is populated. Do I need to do something special with this plugin to get the secondary select box values and lists populated as desired on the edit page?
Here is the code from my domain classes
Consultant domain class
class CdeConsultant {
String ccf_consultant_firm
static hasMany=[contracts:Contract]
static mapping = {
table name: 'cde_consultant'
version false
id column: 'ccf_consultant_id', generator: "assigned"
}
}
Here is the code for my contract domain class
class Contract {
String contractName
int conId
String phone
String projectManagerName
CdeConsultant cdeConsultant
static hasMany=[projectLists:ProjectList]
static mapping = {
table name: 'contract'
version false
id column: 'contracts_id', generator: "assigned"
}
}
Here is the code from my ProjectList domain class
class ProjectList {
String project
Contract contract
static mapping = {
table name: 'project_list'
version false
id column: 'dpp_project_phase_id', generator: "assigned"
contract column: 'contracts_id'
}
}
Here is my code for the evaluation class which is where these fields are being saved
import java.util.Date
class CdeEvaluation extends Base {
String consultant
String consultantName
String project
String projectManager
String projectManagerPhone
String evalStatus
String cdeComment
Date evalBeginDate
Date evalEndDate
String submitApproval
int workCategory
int contract
String contractName
List<CdeEvalQuestion> questions
static hasMany = [questions: CdeEvalQuestion]
static constraints = {
consultant(nullable:true)
consultantName(nullable:true)
project(nullable:true)
contract(nullable:true)
contractName(nullable:true)
projectManager(nullable:true)
projectManagerPhone(nullable:true)
evalStatus(nullable:true)
workCategory(nullable:true)
evalEndDate validator: {value, cdeEvaluation -> value >= cdeEvaluation.evalBeginDate}
cdeComment(nullable:true, maxSize:2000)
submitApproval(nullable:true)
evalBeginDate(blank: false, nullable:true)
evalEndDate(blank: false, nullable:true)
createdBy(blank: false, nullable:true, maxSize:13)
dateCreated(blank: false, nullable:true)
lastUpdatedBy(blank: false, nullable:true, maxSize:13)
lastUpdated(blank: false, nullable:true)
}
static mapping = {
table name: 'CDE_EVALUATION'
id column: 'ceval_id_seq'
id generator: 'sequence', params: [sequence: 'ceval_id_seq']
}
#Override
public String toString() {
"${project}"
}
class EvaluationController {
static scaffold=true
}
}
And finally here is the code for my form template that is used in both the create and edit pages.
<g:selectPrimary class="form-select-list" id="consultant" name="consultant" label="Consultant"
domain='gov.mt.mdt.cde.domain.evaluation.CdeConsultant'
searchField="ccf_consultant_firm"
collectField='id'
domain2='gov.mt.mdt.cde.domain.evaluation.Contract'
bindid="cdeConsultant.id"
searchField2='contractName'
collectField2='id'
noSelection="['': 'Select A Consultant']"
setId="contract"
value="${cdeEvaluationInstance?.consultant}"
appendValue=''
appendName='Select a Contract' />
<g:selectSecondary class="form-select-list" id="contract" name="contract"
domain2='gov.mt.mdt.cde.domain.evaluation.ProjectList'
bindid="contract.id"
searchField2='project'
collectField2='project'
noSelection="['': 'Select A Contract']"
setId="project"
appendValue=''
appendName='Select a Project'
value="${cdeEvaluationInstance?.contract}"
required="false"/>
<g:select class="form-control" name="project" id="project" optionKey="project" optionValue="project"
from="[]" noSelection="['': 'Select A Project']" value="${cdeEvaluationInstance?.project}" />
Sorry a little late to answer your question here, edit I don't think has much documentation :). Although current situation gives me ideas to expand on the plugin for sure...
The problem being the secondary selection is reliant on primary being selected, the selection on primary itself triggers the gathered list for secondary box to be populated. Since primary is already defined not selected - well there you see the issue.
Let me have a think, if you had raised it as issue/suggestion on github I would have got to it earlier.
UPDATE
Ok I have rolled out 0.40 which should hopefully address edit mode :
Please take a look at this page :
https://github.com/vahidhedayati/ajaxdependancyselectexample/blob/master/grails-app/views/myContinent/testedit.gsp
In theory assuming the hardcoded values are returned as dynamic variables from the db an additional definition is required per primary/secondary call:
so in the
value='4'
secondaryValue='10'
Value is its own value and secondaryValue is what you expect to set the next selectSecondary
Please note I had to also remove appendName and appendValue from selectPrimary/selectSecondary calls. I think there was some form of a conflict in the edit mode....
Anyhow that testedit appeared to be working.

Resources